Socket
Socket
Sign inDemoInstall

interweave-autolink

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

interweave-autolink - npm Package Compare versions

Comparing version 4.4.3 to 5.0.0

19

CHANGELOG.md

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

# 5.0.0 - 2022-03-04
#### šŸ’„ Breaking
- Dropped IE 11 support. Modern browsers now required.
#### šŸš€ Updates
- Hashtag matching now supports Chinese, Japanese, Korean, Russian, and other non-latin based characters.
- Added support for React 18.
#### šŸ“¦ Dependencies
- Updated to latest `packemon`.
#### šŸ›  Internals
- Migrated to [Beemo](https://github.com/beemojs/dev) for build and developer tooling.
### 4.4.3 - 2021-07-10

@@ -2,0 +21,0 @@

2

dts/Email.d.ts
/// <reference types="react" />
import { EmailProps } from './types';
export default function Email({ children, email, emailParts, ...props }: EmailProps): JSX.Element;
export declare function Email({ children, email, emailParts, ...props }: EmailProps): JSX.Element;
//# sourceMappingURL=Email.d.ts.map
import { ChildrenNode, Matcher, MatchResponse, Node } from 'interweave';
import { EmailProps } from './types';
export declare type EmailMatch = Pick<EmailProps, 'email' | 'emailParts'>;
export default class EmailMatcher extends Matcher<EmailProps> {
export declare class EmailMatcher extends Matcher<EmailProps> {
replaceWith(children: ChildrenNode, props: EmailProps): Node;

@@ -6,0 +6,0 @@ asTag(): string;

/// <reference types="react" />
import { HashtagProps } from './types';
export default function Hashtag({ children, encodeHashtag, hashtag, hashtagUrl, preserveHash, ...props }: HashtagProps): JSX.Element;
export declare function Hashtag({ children, encodeHashtag, hashtag, hashtagUrl, preserveHash, ...props }: HashtagProps): JSX.Element;
//# sourceMappingURL=Hashtag.d.ts.map
import { ChildrenNode, Matcher, MatchResponse, Node } from 'interweave';
import { HashtagProps } from './types';
export declare type HashtagMatch = Pick<HashtagProps, 'hashtag'>;
export default class HashtagMatcher extends Matcher<HashtagProps> {
export declare class HashtagMatcher extends Matcher<HashtagProps> {
replaceWith(children: ChildrenNode, props: HashtagProps): Node;

@@ -6,0 +6,0 @@ asTag(): string;

/**
* @copyright 2016-2019, Miles Johnson
* @copyright 2021, Miles Johnson
* @license https://opensource.org/licenses/MIT
*/
import Email from './Email';
import EmailMatcher from './EmailMatcher';
import Hashtag from './Hashtag';
import HashtagMatcher from './HashtagMatcher';
import IpMatcher from './IpMatcher';
import Link from './Link';
import Url from './Url';
import UrlMatcher from './UrlMatcher';
export { Email, EmailMatcher, Hashtag, HashtagMatcher, IpMatcher, Link, Url, UrlMatcher };
export * from './constants';
export * from './Email';
export * from './EmailMatcher';
export * from './Hashtag';
export * from './HashtagMatcher';
export * from './IpMatcher';
export * from './Link';
export * from './types';
export * from './Url';
export * from './UrlMatcher';
//# sourceMappingURL=index.d.ts.map
import React from 'react';
import { MatchResponse } from 'interweave';
import { UrlMatcherOptions, UrlProps } from './types';
import UrlMatcher, { UrlMatch } from './UrlMatcher';
export default class IpMatcher extends UrlMatcher {
import { UrlMatch, UrlMatcher } from './UrlMatcher';
export declare class IpMatcher extends UrlMatcher {
constructor(name: string, options?: UrlMatcherOptions, factory?: React.ComponentType<UrlProps> | null);

@@ -7,0 +7,0 @@ match(string: string): MatchResponse<UrlMatch> | null;

/// <reference types="react" />
import { LinkProps } from './types';
export default function Link({ children, href, onClick, newWindow }: LinkProps): JSX.Element;
export declare function Link({ children, href, onClick, newWindow }: LinkProps): JSX.Element;
//# sourceMappingURL=Link.d.ts.map
/// <reference types="react" />
import { UrlProps } from './types';
export default function Url({ children, url, urlParts, ...props }: UrlProps): JSX.Element;
export declare function Url({ children, url, urlParts, ...props }: UrlProps): JSX.Element;
//# sourceMappingURL=Url.d.ts.map

@@ -5,3 +5,3 @@ import React from 'react';

export declare type UrlMatch = Pick<UrlProps, 'url' | 'urlParts'>;
export default class UrlMatcher extends Matcher<UrlProps, UrlMatcherOptions> {
export declare class UrlMatcher extends Matcher<UrlProps, UrlMatcherOptions> {
constructor(name: string, options?: UrlMatcherOptions, factory?: React.ComponentType<UrlProps> | null);

@@ -8,0 +8,0 @@ replaceWith(children: ChildrenNode, props: UrlProps): Node;

@@ -1,71 +0,16 @@

function _extends2() { _extends2 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends2.apply(this, arguments); }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
// Generated with Packemon: https://packemon.dev
// Bundled with Packemon: https://packemon.dev
// Platform: browser, Support: stable, Format: esm
import React from 'react';
import { Matcher } from 'interweave';
/* eslint-disable unicorn/better-regex, unicorn/no-unsafe-regex */
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
function combinePatterns(patterns, options = {}) {
var _options$join, _options$flags;
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
let regex = patterns.map(pattern => pattern.source).join((_options$join = options.join) !== null && _options$join !== void 0 ? _options$join : '');
return target;
};
return _extends.apply(this, arguments);
}
function Link(_ref) {
var children = _ref.children,
href = _ref.href,
onClick = _ref.onClick,
newWindow = _ref.newWindow;
return /*#__PURE__*/React.createElement("a", {
href: href,
target: newWindow ? '_blank' : undefined,
onClick: onClick,
rel: "noopener noreferrer"
}, children);
}
function Email(_ref2) {
var children = _ref2.children,
email = _ref2.email,
emailParts = _ref2.emailParts,
props = _objectWithoutPropertiesLoose(_ref2, ["children", "email", "emailParts"]);
return /*#__PURE__*/React.createElement(Link, _extends({}, props, {
href: "mailto:" + email
}), children);
}
/* eslint-disable unicorn/better-regex */
function combinePatterns(patterns, options) {
if (options === void 0) {
options = {};
}
var regex = patterns.map(function (pattern) {
return pattern.source;
}).join(options.join || '');
if (options.capture) {
regex = "(" + regex + ")";
regex = `(${regex})`;
} else if (options.nonCapture) {
regex = "(?:" + regex + ")";
regex = `(?:${regex})`;
}

@@ -77,3 +22,3 @@

return new RegExp(regex, options.flags || '');
return new RegExp(regex, (_options$flags = options.flags) !== null && _options$flags !== void 0 ? _options$flags : '');
} // https://www.ietf.org/rfc/rfc3986.txt

@@ -84,6 +29,6 @@ // https://blog.codinghorror.com/the-problem-with-urls/

var VALID_ALNUM_CHARS = /[a-z0-9]/;
var VALID_PATH_CHARS = /(?:[a-zA-Z\u0400-\u04FF0-9\-_~!$&'()[\]\\/*+,;=.%]*)/;
var URL_SCHEME = /(https?:\/\/)?/;
var URL_AUTH = combinePatterns([/[a-z\u0400-\u04FF0-9\-_~!$&'()*+,;=.:]+/, // Includes colon
const VALID_ALNUM_CHARS = /[a-z0-9]/;
const VALID_PATH_CHARS = /(?:[a-zA-Z\u0400-\u04FF0-9\-_~!$&'()[\]\\/*+,;=.%]*)/;
const URL_SCHEME = /(https?:\/\/)?/;
const URL_AUTH = combinePatterns([/[a-z\u0400-\u04FF0-9\-_~!$&'()*+,;=.:]+/, // Includes colon
/@/], {

@@ -93,3 +38,3 @@ capture: true,

});
var URL_HOST = combinePatterns([/(?:(?:[a-z0-9](?:[-a-z0-9_]*[a-z0-9])?)\.)*/, // Subdomain
const URL_HOST = combinePatterns([/(?:(?:[a-z0-9](?:[-a-z0-9_]*[a-z0-9])?)\.)*/, // Subdomain
/(?:(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?)\.)/, // Domain

@@ -100,4 +45,4 @@ /(?:[a-z](?:[-a-z0-9]*[a-z0-9])?)/ // TLD

});
var URL_PORT = /(?::(\d{1,5}))?/;
var URL_PATH = combinePatterns([/\//, combinePatterns([/[-+a-z0-9!*';:=,.$/%[\]_~@|&]*/, /[-+a-z0-9/]/ // Valid ending chars
const URL_PORT = /(?::(\d{1,5}))?/;
const URL_PATH = combinePatterns([/\//, combinePatterns([/[-+a-z0-9!*';:=,.$/%[\]_~@|&]*/, /[-+a-z0-9/]/ // Valid ending chars
], {

@@ -110,3 +55,3 @@ match: '*',

});
var URL_QUERY = combinePatterns([/\?/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9_&=]/ // Valid ending chars
const URL_QUERY = combinePatterns([/\?/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9_&=]/ // Valid ending chars
], {

@@ -119,3 +64,3 @@ match: '?',

});
var URL_FRAGMENT = combinePatterns([/#/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9]/ // Valid ending chars
const URL_FRAGMENT = combinePatterns([/#/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9]/ // Valid ending chars
], {

@@ -128,31 +73,40 @@ match: '?',

});
var URL_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, URL_HOST, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
const URL_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, URL_HOST, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
flags: 'i'
});
var IP_V4_PART = /(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/;
var IP_V4 = combinePatterns([IP_V4_PART, IP_V4_PART, IP_V4_PART, IP_V4_PART], {
const IP_V4_PART = /(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/;
const IP_V4 = combinePatterns([IP_V4_PART, IP_V4_PART, IP_V4_PART, IP_V4_PART], {
capture: true,
join: '\\.'
});
var IP_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, IP_V4, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
const IP_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, IP_V4, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
flags: 'i'
});
var HASHTAG_PATTERN = combinePatterns([/#/, combinePatterns([VALID_ALNUM_CHARS, /[-a-z0-9_]*/], {
capture: true
const NON_LATIN = [// Chinese
/[\d_\u4E00-\u9FFF-]+/, // Japanese
/[\d_\u3000-\u30FF-]+/, // Korean
/[\d_\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uAC00-\uD7FF-]+/, // Thai
/[\d_\u0E00-\u0E7F-]+/, // Russian, Ukrainian
// eslint-disable-next-line no-misleading-character-class
/[\d_a-z\u0400-\u052F\u1C80-\u1C8F\u2DE0-\u2DFF\uA640-\uA69F-]+/, // Latin based
/[\d_a-z\u0080-\u00FF\u0100-\u017F\u0180-\u024F-]+/];
const HASHTAG_PATTERN = combinePatterns([/#/, combinePatterns(NON_LATIN, {
capture: true,
join: '|'
})], {
flags: 'i'
});
var EMAIL_USERNAME_PART = /[.a-z0-9!#$%&?*+=_{|}~-]*/;
var EMAIL_USERNAME = combinePatterns([VALID_ALNUM_CHARS, EMAIL_USERNAME_PART, VALID_ALNUM_CHARS], {
const EMAIL_USERNAME_PART = /[.a-z0-9!#$%&?*+=_{|}~-]*/;
const EMAIL_USERNAME = combinePatterns([VALID_ALNUM_CHARS, EMAIL_USERNAME_PART, VALID_ALNUM_CHARS], {
capture: true
});
var EMAIL_PATTERN = combinePatterns([EMAIL_USERNAME, URL_HOST], {
const EMAIL_PATTERN = combinePatterns([EMAIL_USERNAME, URL_HOST], {
flags: 'i',
join: '@'
});
var EMAIL_DISTINCT_PATTERN = new RegExp("^" + EMAIL_PATTERN.source + "$", EMAIL_PATTERN.flags); // Properly and efficiently detecting URLs + all TLDs is nigh impossible,
const EMAIL_DISTINCT_PATTERN = new RegExp(`^${EMAIL_PATTERN.source}$`, EMAIL_PATTERN.flags); // Properly and efficiently detecting URLs + all TLDs is nigh impossible,
// instead we will only support the most common top-level TLDs.
// https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
var TOP_LEVEL_TLDS = [// Original
const TOP_LEVEL_TLDS = [// Original
'com', 'org', 'net', 'int', 'edu', 'gov', 'mil', // Sponsored

@@ -417,48 +371,77 @@ 'aero', 'asia', 'biz', 'cat', 'coop', 'jobs', 'mobi', 'museum', 'post', 'tel', 'travel', 'xxx', // Misc

var EmailMatcher = /*#__PURE__*/function (_Matcher) {
_inheritsLoose(EmailMatcher, _Matcher);
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
function EmailMatcher() {
return _Matcher.apply(this, arguments) || this;
}
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
var _proto = EmailMatcher.prototype;
return target;
};
_proto.replaceWith = function replaceWith(children, props) {
return _extends.apply(this, arguments);
}
function Link({
children,
href,
onClick,
newWindow
}) {
return /*#__PURE__*/React.createElement("a", {
href: href,
rel: "noopener noreferrer",
target: newWindow ? '_blank' : undefined,
onClick: onClick
}, children);
}
function Email({
children,
email,
emailParts,
...props
}) {
return /*#__PURE__*/React.createElement(Link, _extends({}, props, {
href: `mailto:${email}`
}), children);
}
class EmailMatcher extends Matcher {
replaceWith(children, props) {
return /*#__PURE__*/React.createElement(Email, props, children);
};
}
_proto.asTag = function asTag() {
asTag() {
return 'a';
};
}
_proto.match = function match(string) {
return this.doMatch(string, EMAIL_PATTERN, function (matches) {
return {
email: matches[0],
emailParts: {
host: matches[2],
username: matches[1]
}
};
});
};
match(string) {
return this.doMatch(string, EMAIL_PATTERN, matches => ({
email: matches[0],
emailParts: {
host: matches[2],
username: matches[1]
}
}));
}
return EmailMatcher;
}(Matcher);
}
function Hashtag(_ref3) {
var children = _ref3.children,
_ref3$encodeHashtag = _ref3.encodeHashtag,
encodeHashtag = _ref3$encodeHashtag === void 0 ? false : _ref3$encodeHashtag,
hashtag = _ref3.hashtag,
_ref3$hashtagUrl = _ref3.hashtagUrl,
hashtagUrl = _ref3$hashtagUrl === void 0 ? '{{hashtag}}' : _ref3$hashtagUrl,
_ref3$preserveHash = _ref3.preserveHash,
preserveHash = _ref3$preserveHash === void 0 ? false : _ref3$preserveHash,
props = _objectWithoutPropertiesLoose(_ref3, ["children", "encodeHashtag", "hashtag", "hashtagUrl", "preserveHash"]);
function Hashtag({
children,
encodeHashtag = false,
hashtag,
hashtagUrl = '{{hashtag}}',
preserveHash = false,
...props
}) {
let tag = hashtag; // Prepare the hashtag
var tag = hashtag; // Prepare the hashtag
if (!preserveHash && tag.charAt(0) === '#') {
if (!preserveHash && tag.startsWith('#')) {
tag = tag.slice(1);

@@ -472,3 +455,3 @@ }

var url = hashtagUrl || '{{hashtag}}';
let url = hashtagUrl || '{{hashtag}}';
url = typeof url === 'function' ? url(tag) : url.replace('{{hashtag}}', tag);

@@ -480,40 +463,29 @@ return /*#__PURE__*/React.createElement(Link, _extends({}, props, {

var HashtagMatcher = /*#__PURE__*/function (_Matcher2) {
_inheritsLoose(HashtagMatcher, _Matcher2);
function HashtagMatcher() {
return _Matcher2.apply(this, arguments) || this;
class HashtagMatcher extends Matcher {
replaceWith(children, props) {
return /*#__PURE__*/React.createElement(Hashtag, props, children);
}
var _proto2 = HashtagMatcher.prototype;
_proto2.replaceWith = function replaceWith(children, props) {
return /*#__PURE__*/React.createElement(Hashtag, props, children);
};
_proto2.asTag = function asTag() {
asTag() {
return 'a';
};
}
_proto2.match = function match(string) {
return this.doMatch(string, HASHTAG_PATTERN, function (matches) {
return {
hashtag: matches[0]
};
});
};
match(string) {
return this.doMatch(string, HASHTAG_PATTERN, matches => ({
hashtag: matches[0]
}));
}
return HashtagMatcher;
}(Matcher);
}
function Url(_ref4) {
var children = _ref4.children,
url = _ref4.url,
urlParts = _ref4.urlParts,
props = _objectWithoutPropertiesLoose(_ref4, ["children", "url", "urlParts"]);
function Url({
children,
url,
urlParts,
...props
}) {
let href = url;
var href = url;
if (!href.match(/^https?:\/\//)) {
href = "http://" + href;
href = `http://${href}`;
}

@@ -526,34 +498,35 @@

var UrlMatcher = /*#__PURE__*/function (_Matcher3) {
_inheritsLoose(UrlMatcher, _Matcher3);
function UrlMatcher(name, options, factory) {
return _Matcher3.call(this, name, _extends2({
class UrlMatcher extends Matcher {
constructor(name, options, factory) {
super(name, {
customTLDs: [],
validateTLD: true
}, options), factory) || this;
validateTLD: true,
...options
}, factory);
}
var _proto3 = UrlMatcher.prototype;
_proto3.replaceWith = function replaceWith(children, props) {
replaceWith(children, props) {
return /*#__PURE__*/React.createElement(Url, props, children);
};
}
_proto3.asTag = function asTag() {
asTag() {
return 'a';
};
}
_proto3.match = function match(string) {
var response = this.doMatch(string, URL_PATTERN, this.handleMatches); // False positives with URL auth scheme
match(string) {
const response = this.doMatch(string, URL_PATTERN, this.handleMatches); // False positives with URL auth scheme
if (response != null && response.match.match(EMAIL_DISTINCT_PATTERN)) {
if (response !== null && response !== void 0 && response.match.match(EMAIL_DISTINCT_PATTERN)) {
response.valid = false;
}
if (response != null && response.valid && this.options.validateTLD) {
var host = response.urlParts.host;
var validList = TOP_LEVEL_TLDS.concat(this.options.customTLDs || []);
var tld = host.slice(host.lastIndexOf('.') + 1).toLowerCase();
if (response !== null && response !== void 0 && response.valid && this.options.validateTLD) {
var _this$options$customT;
const {
host
} = response.urlParts;
const validList = [...TOP_LEVEL_TLDS, ...((_this$options$customT = this.options.customTLDs) !== null && _this$options$customT !== void 0 ? _this$options$customT : [])];
const tld = host.slice(host.lastIndexOf('.') + 1).toLowerCase();
if (!validList.includes(tld)) {

@@ -569,5 +542,5 @@ return null;

*/
;
_proto3.handleMatches = function handleMatches(matches) {
handleMatches(matches) {
return {

@@ -585,27 +558,21 @@ url: matches[0],

};
};
}
return UrlMatcher;
}(Matcher);
}
var IpMatcher = /*#__PURE__*/function (_UrlMatcher) {
_inheritsLoose(IpMatcher, _UrlMatcher);
function IpMatcher(name, options, factory) {
return _UrlMatcher.call(this, name, _extends2({}, options, {
class IpMatcher extends UrlMatcher {
constructor(name, options, factory) {
super(name, { ...options,
// IPs dont have TLDs
validateTLD: false
}), factory) || this;
}, factory);
}
var _proto4 = IpMatcher.prototype;
_proto4.match = function match(string) {
match(string) {
return this.doMatch(string, IP_PATTERN, this.handleMatches);
};
}
return IpMatcher;
}(UrlMatcher);
}
export { EMAIL_DISTINCT_PATTERN, EMAIL_PATTERN, EMAIL_USERNAME, EMAIL_USERNAME_PART, Email, EmailMatcher, HASHTAG_PATTERN, Hashtag, HashtagMatcher, IP_PATTERN, IP_V4, IP_V4_PART, IpMatcher, Link, TOP_LEVEL_TLDS, URL_AUTH, URL_FRAGMENT, URL_HOST, URL_PATH, URL_PATTERN, URL_PORT, URL_QUERY, URL_SCHEME, Url, UrlMatcher, VALID_ALNUM_CHARS, VALID_PATH_CHARS, combinePatterns };
//# sourceMappingURL=index.js.map

@@ -1,86 +0,35 @@

// Generated with Packemon: https://packemon.dev
// Bundled with Packemon: https://packemon.dev
// Platform: browser, Support: stable, Format: lib
'use strict';
function _extends2() { _extends2 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends2.apply(this, arguments); }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
Object.defineProperty(exports, '__esModule', {
value: true
Object.defineProperties(exports, {
__esModule: {
value: true
},
[Symbol.toStringTag]: {
value: 'Module'
}
});
var React = require('react');
const React = require('react');
var interweave = require('interweave');
const interweave = require('interweave');
function _interopDefaultLegacy(e) {
return e && typeof e === 'object' && 'default' in e ? e : {
'default': e
};
}
const _interopDefault = e => e && e.__esModule ? e : {
default: e
};
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
const React__default = /*#__PURE__*/_interopDefault(React);
/* eslint-disable unicorn/better-regex, unicorn/no-unsafe-regex */
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
function combinePatterns(patterns, options = {}) {
var _options$join, _options$flags;
return target;
};
let regex = patterns.map(pattern => pattern.source).join((_options$join = options.join) !== null && _options$join !== void 0 ? _options$join : '');
return _extends.apply(this, arguments);
}
function Link(_ref) {
var children = _ref.children,
href = _ref.href,
onClick = _ref.onClick,
newWindow = _ref.newWindow;
return /*#__PURE__*/React__default['default'].createElement("a", {
href: href,
target: newWindow ? '_blank' : undefined,
onClick: onClick,
rel: "noopener noreferrer"
}, children);
}
function Email(_ref2) {
var children = _ref2.children,
email = _ref2.email,
emailParts = _ref2.emailParts,
props = _objectWithoutPropertiesLoose(_ref2, ["children", "email", "emailParts"]);
return /*#__PURE__*/React__default['default'].createElement(Link, _extends({}, props, {
href: "mailto:" + email
}), children);
}
/* eslint-disable unicorn/better-regex */
function combinePatterns(patterns, options) {
if (options === void 0) {
options = {};
}
var regex = patterns.map(function (pattern) {
return pattern.source;
}).join(options.join || '');
if (options.capture) {
regex = "(" + regex + ")";
regex = `(${regex})`;
} else if (options.nonCapture) {
regex = "(?:" + regex + ")";
regex = `(?:${regex})`;
}

@@ -92,3 +41,3 @@

return new RegExp(regex, options.flags || '');
return new RegExp(regex, (_options$flags = options.flags) !== null && _options$flags !== void 0 ? _options$flags : '');
} // https://www.ietf.org/rfc/rfc3986.txt

@@ -99,6 +48,6 @@ // https://blog.codinghorror.com/the-problem-with-urls/

var VALID_ALNUM_CHARS = /[a-z0-9]/;
var VALID_PATH_CHARS = /(?:[a-zA-Z\u0400-\u04FF0-9\-_~!$&'()[\]\\/*+,;=.%]*)/;
var URL_SCHEME = /(https?:\/\/)?/;
var URL_AUTH = combinePatterns([/[a-z\u0400-\u04FF0-9\-_~!$&'()*+,;=.:]+/, // Includes colon
const VALID_ALNUM_CHARS = /[a-z0-9]/;
const VALID_PATH_CHARS = /(?:[a-zA-Z\u0400-\u04FF0-9\-_~!$&'()[\]\\/*+,;=.%]*)/;
const URL_SCHEME = /(https?:\/\/)?/;
const URL_AUTH = combinePatterns([/[a-z\u0400-\u04FF0-9\-_~!$&'()*+,;=.:]+/, // Includes colon
/@/], {

@@ -108,3 +57,3 @@ capture: true,

});
var URL_HOST = combinePatterns([/(?:(?:[a-z0-9](?:[-a-z0-9_]*[a-z0-9])?)\.)*/, // Subdomain
const URL_HOST = combinePatterns([/(?:(?:[a-z0-9](?:[-a-z0-9_]*[a-z0-9])?)\.)*/, // Subdomain
/(?:(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?)\.)/, // Domain

@@ -115,4 +64,4 @@ /(?:[a-z](?:[-a-z0-9]*[a-z0-9])?)/ // TLD

});
var URL_PORT = /(?::(\d{1,5}))?/;
var URL_PATH = combinePatterns([/\//, combinePatterns([/[-+a-z0-9!*';:=,.$/%[\]_~@|&]*/, /[-+a-z0-9/]/ // Valid ending chars
const URL_PORT = /(?::(\d{1,5}))?/;
const URL_PATH = combinePatterns([/\//, combinePatterns([/[-+a-z0-9!*';:=,.$/%[\]_~@|&]*/, /[-+a-z0-9/]/ // Valid ending chars
], {

@@ -125,3 +74,3 @@ match: '*',

});
var URL_QUERY = combinePatterns([/\?/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9_&=]/ // Valid ending chars
const URL_QUERY = combinePatterns([/\?/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9_&=]/ // Valid ending chars
], {

@@ -134,3 +83,3 @@ match: '?',

});
var URL_FRAGMENT = combinePatterns([/#/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9]/ // Valid ending chars
const URL_FRAGMENT = combinePatterns([/#/, combinePatterns([VALID_PATH_CHARS, /[a-z0-9]/ // Valid ending chars
], {

@@ -143,31 +92,40 @@ match: '?',

});
var URL_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, URL_HOST, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
const URL_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, URL_HOST, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
flags: 'i'
});
var IP_V4_PART = /(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/;
var IP_V4 = combinePatterns([IP_V4_PART, IP_V4_PART, IP_V4_PART, IP_V4_PART], {
const IP_V4_PART = /(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/;
const IP_V4 = combinePatterns([IP_V4_PART, IP_V4_PART, IP_V4_PART, IP_V4_PART], {
capture: true,
join: '\\.'
});
var IP_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, IP_V4, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
const IP_PATTERN = combinePatterns([URL_SCHEME, URL_AUTH, IP_V4, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT], {
flags: 'i'
});
var HASHTAG_PATTERN = combinePatterns([/#/, combinePatterns([VALID_ALNUM_CHARS, /[-a-z0-9_]*/], {
capture: true
const NON_LATIN = [// Chinese
/[\d_\u4E00-\u9FFF-]+/, // Japanese
/[\d_\u3000-\u30FF-]+/, // Korean
/[\d_\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uAC00-\uD7FF-]+/, // Thai
/[\d_\u0E00-\u0E7F-]+/, // Russian, Ukrainian
// eslint-disable-next-line no-misleading-character-class
/[\d_a-z\u0400-\u052F\u1C80-\u1C8F\u2DE0-\u2DFF\uA640-\uA69F-]+/, // Latin based
/[\d_a-z\u0080-\u00FF\u0100-\u017F\u0180-\u024F-]+/];
const HASHTAG_PATTERN = combinePatterns([/#/, combinePatterns(NON_LATIN, {
capture: true,
join: '|'
})], {
flags: 'i'
});
var EMAIL_USERNAME_PART = /[.a-z0-9!#$%&?*+=_{|}~-]*/;
var EMAIL_USERNAME = combinePatterns([VALID_ALNUM_CHARS, EMAIL_USERNAME_PART, VALID_ALNUM_CHARS], {
const EMAIL_USERNAME_PART = /[.a-z0-9!#$%&?*+=_{|}~-]*/;
const EMAIL_USERNAME = combinePatterns([VALID_ALNUM_CHARS, EMAIL_USERNAME_PART, VALID_ALNUM_CHARS], {
capture: true
});
var EMAIL_PATTERN = combinePatterns([EMAIL_USERNAME, URL_HOST], {
const EMAIL_PATTERN = combinePatterns([EMAIL_USERNAME, URL_HOST], {
flags: 'i',
join: '@'
});
var EMAIL_DISTINCT_PATTERN = new RegExp("^" + EMAIL_PATTERN.source + "$", EMAIL_PATTERN.flags); // Properly and efficiently detecting URLs + all TLDs is nigh impossible,
const EMAIL_DISTINCT_PATTERN = new RegExp(`^${EMAIL_PATTERN.source}$`, EMAIL_PATTERN.flags); // Properly and efficiently detecting URLs + all TLDs is nigh impossible,
// instead we will only support the most common top-level TLDs.
// https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
var TOP_LEVEL_TLDS = [// Original
const TOP_LEVEL_TLDS = [// Original
'com', 'org', 'net', 'int', 'edu', 'gov', 'mil', // Sponsored

@@ -432,48 +390,77 @@ 'aero', 'asia', 'biz', 'cat', 'coop', 'jobs', 'mobi', 'museum', 'post', 'tel', 'travel', 'xxx', // Misc

var EmailMatcher = /*#__PURE__*/function (_interweave$Matcher) {
_inheritsLoose(EmailMatcher, _interweave$Matcher);
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
function EmailMatcher() {
return _interweave$Matcher.apply(this, arguments) || this;
}
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
var _proto = EmailMatcher.prototype;
_proto.replaceWith = function replaceWith(children, props) {
return /*#__PURE__*/React__default['default'].createElement(Email, props, children);
return target;
};
_proto.asTag = function asTag() {
return _extends.apply(this, arguments);
}
function Link({
children,
href,
onClick,
newWindow
}) {
return /*#__PURE__*/React__default.default.createElement("a", {
href: href,
rel: "noopener noreferrer",
target: newWindow ? '_blank' : undefined,
onClick: onClick
}, children);
}
function Email({
children,
email,
emailParts,
...props
}) {
return /*#__PURE__*/React__default.default.createElement(Link, _extends({}, props, {
href: `mailto:${email}`
}), children);
}
class EmailMatcher extends interweave.Matcher {
replaceWith(children, props) {
return /*#__PURE__*/React__default.default.createElement(Email, props, children);
}
asTag() {
return 'a';
};
}
_proto.match = function match(string) {
return this.doMatch(string, EMAIL_PATTERN, function (matches) {
return {
email: matches[0],
emailParts: {
host: matches[2],
username: matches[1]
}
};
});
};
match(string) {
return this.doMatch(string, EMAIL_PATTERN, matches => ({
email: matches[0],
emailParts: {
host: matches[2],
username: matches[1]
}
}));
}
return EmailMatcher;
}(interweave.Matcher);
}
function Hashtag(_ref3) {
var children = _ref3.children,
_ref3$encodeHashtag = _ref3.encodeHashtag,
encodeHashtag = _ref3$encodeHashtag === void 0 ? false : _ref3$encodeHashtag,
hashtag = _ref3.hashtag,
_ref3$hashtagUrl = _ref3.hashtagUrl,
hashtagUrl = _ref3$hashtagUrl === void 0 ? '{{hashtag}}' : _ref3$hashtagUrl,
_ref3$preserveHash = _ref3.preserveHash,
preserveHash = _ref3$preserveHash === void 0 ? false : _ref3$preserveHash,
props = _objectWithoutPropertiesLoose(_ref3, ["children", "encodeHashtag", "hashtag", "hashtagUrl", "preserveHash"]);
function Hashtag({
children,
encodeHashtag = false,
hashtag,
hashtagUrl = '{{hashtag}}',
preserveHash = false,
...props
}) {
let tag = hashtag; // Prepare the hashtag
var tag = hashtag; // Prepare the hashtag
if (!preserveHash && tag.charAt(0) === '#') {
if (!preserveHash && tag.startsWith('#')) {
tag = tag.slice(1);

@@ -487,5 +474,5 @@ }

var url = hashtagUrl || '{{hashtag}}';
let url = hashtagUrl || '{{hashtag}}';
url = typeof url === 'function' ? url(tag) : url.replace('{{hashtag}}', tag);
return /*#__PURE__*/React__default['default'].createElement(Link, _extends({}, props, {
return /*#__PURE__*/React__default.default.createElement(Link, _extends({}, props, {
href: url

@@ -495,43 +482,32 @@ }), children);

var HashtagMatcher = /*#__PURE__*/function (_interweave$Matcher2) {
_inheritsLoose(HashtagMatcher, _interweave$Matcher2);
function HashtagMatcher() {
return _interweave$Matcher2.apply(this, arguments) || this;
class HashtagMatcher extends interweave.Matcher {
replaceWith(children, props) {
return /*#__PURE__*/React__default.default.createElement(Hashtag, props, children);
}
var _proto2 = HashtagMatcher.prototype;
_proto2.replaceWith = function replaceWith(children, props) {
return /*#__PURE__*/React__default['default'].createElement(Hashtag, props, children);
};
_proto2.asTag = function asTag() {
asTag() {
return 'a';
};
}
_proto2.match = function match(string) {
return this.doMatch(string, HASHTAG_PATTERN, function (matches) {
return {
hashtag: matches[0]
};
});
};
match(string) {
return this.doMatch(string, HASHTAG_PATTERN, matches => ({
hashtag: matches[0]
}));
}
return HashtagMatcher;
}(interweave.Matcher);
}
function Url(_ref4) {
var children = _ref4.children,
url = _ref4.url,
urlParts = _ref4.urlParts,
props = _objectWithoutPropertiesLoose(_ref4, ["children", "url", "urlParts"]);
function Url({
children,
url,
urlParts,
...props
}) {
let href = url;
var href = url;
if (!href.match(/^https?:\/\//)) {
href = "http://" + href;
href = `http://${href}`;
}
return /*#__PURE__*/React__default['default'].createElement(Link, _extends({}, props, {
return /*#__PURE__*/React__default.default.createElement(Link, _extends({}, props, {
href: href

@@ -541,34 +517,35 @@ }), children);

var UrlMatcher = /*#__PURE__*/function (_interweave$Matcher3) {
_inheritsLoose(UrlMatcher, _interweave$Matcher3);
function UrlMatcher(name, options, factory) {
return _interweave$Matcher3.call(this, name, _extends2({
class UrlMatcher extends interweave.Matcher {
constructor(name, options, factory) {
super(name, {
customTLDs: [],
validateTLD: true
}, options), factory) || this;
validateTLD: true,
...options
}, factory);
}
var _proto3 = UrlMatcher.prototype;
replaceWith(children, props) {
return /*#__PURE__*/React__default.default.createElement(Url, props, children);
}
_proto3.replaceWith = function replaceWith(children, props) {
return /*#__PURE__*/React__default['default'].createElement(Url, props, children);
};
_proto3.asTag = function asTag() {
asTag() {
return 'a';
};
}
_proto3.match = function match(string) {
var response = this.doMatch(string, URL_PATTERN, this.handleMatches); // False positives with URL auth scheme
match(string) {
const response = this.doMatch(string, URL_PATTERN, this.handleMatches); // False positives with URL auth scheme
if (response != null && response.match.match(EMAIL_DISTINCT_PATTERN)) {
if (response !== null && response !== void 0 && response.match.match(EMAIL_DISTINCT_PATTERN)) {
response.valid = false;
}
if (response != null && response.valid && this.options.validateTLD) {
var host = response.urlParts.host;
var validList = TOP_LEVEL_TLDS.concat(this.options.customTLDs || []);
var tld = host.slice(host.lastIndexOf('.') + 1).toLowerCase();
if (response !== null && response !== void 0 && response.valid && this.options.validateTLD) {
var _this$options$customT;
const {
host
} = response.urlParts;
const validList = [...TOP_LEVEL_TLDS, ...((_this$options$customT = this.options.customTLDs) !== null && _this$options$customT !== void 0 ? _this$options$customT : [])];
const tld = host.slice(host.lastIndexOf('.') + 1).toLowerCase();
if (!validList.includes(tld)) {

@@ -584,5 +561,5 @@ return null;

*/
;
_proto3.handleMatches = function handleMatches(matches) {
handleMatches(matches) {
return {

@@ -600,25 +577,19 @@ url: matches[0],

};
};
}
return UrlMatcher;
}(interweave.Matcher);
}
var IpMatcher = /*#__PURE__*/function (_UrlMatcher) {
_inheritsLoose(IpMatcher, _UrlMatcher);
function IpMatcher(name, options, factory) {
return _UrlMatcher.call(this, name, _extends2({}, options, {
class IpMatcher extends UrlMatcher {
constructor(name, options, factory) {
super(name, { ...options,
// IPs dont have TLDs
validateTLD: false
}), factory) || this;
}, factory);
}
var _proto4 = IpMatcher.prototype;
_proto4.match = function match(string) {
match(string) {
return this.doMatch(string, IP_PATTERN, this.handleMatches);
};
}
return IpMatcher;
}(UrlMatcher);
}

@@ -625,0 +596,0 @@ exports.EMAIL_DISTINCT_PATTERN = EMAIL_DISTINCT_PATTERN;

{
"name": "interweave-autolink",
"version": "4.4.3",
"version": "5.0.0",
"description": "URL, IP, email, and hashtag autolinking support for Interweave.",

@@ -35,7 +35,7 @@ "keywords": [

"peerDependencies": {
"interweave": "^12.0.0",
"react": "^16.8.0 || ^17.0.0"
"interweave": "^13.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"devDependencies": {
"interweave-ssr": "^1.2.1",
"interweave-ssr": "^2.0.0",
"react": "^17.0.2"

@@ -50,3 +50,3 @@ },

},
"gitHead": "d66d6457185b74038df4f6b2afba5968147c5e55"
"gitHead": "09dba2f437ecff7673bd8ac2ca20232df42361a0"
}

@@ -12,4 +12,4 @@ # Interweave with Autolinking

<Interweave
content="This contains a URL, https://github.com/milesj/interweave, and a hashtag, #interweave, that will be converted to an anchor link!"
matchers={[new UrlMatcher('url'), new HashtagMatcher('hashtag')]}
content="This contains a URL, https://github.com/milesj/interweave, and a hashtag, #interweave, that will be converted to an anchor link!"
matchers={[new UrlMatcher('url'), new HashtagMatcher('hashtag')]}
/>

@@ -16,0 +16,0 @@ ```

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

/* eslint-disable unicorn/better-regex */
/* eslint-disable unicorn/better-regex, unicorn/no-unsafe-regex */
export interface CombinePatternsOptions {
capture?: boolean;
flags?: string;
join?: string;
match?: string;
nonCapture?: boolean;
capture?: boolean;
flags?: string;
join?: string;
match?: string;
nonCapture?: boolean;
}
export function combinePatterns(patterns: RegExp[], options: CombinePatternsOptions = {}) {
let regex = patterns.map((pattern) => pattern.source).join(options.join || '');
let regex = patterns.map((pattern) => pattern.source).join(options.join ?? '');
if (options.capture) {
regex = `(${regex})`;
} else if (options.nonCapture) {
regex = `(?:${regex})`;
}
if (options.capture) {
regex = `(${regex})`;
} else if (options.nonCapture) {
regex = `(?:${regex})`;
}
if (options.match) {
regex += options.match;
}
if (options.match) {
regex += options.match;
}
return new RegExp(regex, options.flags || '');
return new RegExp(regex, options.flags ?? '');
}

@@ -37,21 +37,21 @@

export const URL_AUTH = combinePatterns(
[
/[a-z\u0400-\u04FF0-9\-_~!$&'()*+,;=.:]+/, // Includes colon
/@/,
],
{
capture: true,
match: '?',
},
[
/[a-z\u0400-\u04FF0-9\-_~!$&'()*+,;=.:]+/, // Includes colon
/@/,
],
{
capture: true,
match: '?',
},
);
export const URL_HOST = combinePatterns(
[
/(?:(?:[a-z0-9](?:[-a-z0-9_]*[a-z0-9])?)\.)*/, // Subdomain
/(?:(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?)\.)/, // Domain
/(?:[a-z](?:[-a-z0-9]*[a-z0-9])?)/, // TLD
],
{
capture: true,
},
[
/(?:(?:[a-z0-9](?:[-a-z0-9_]*[a-z0-9])?)\.)*/, // Subdomain
/(?:(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?)\.)/, // Domain
/(?:[a-z](?:[-a-z0-9]*[a-z0-9])?)/, // TLD
],
{
capture: true,
},
);

@@ -62,66 +62,66 @@

export const URL_PATH = combinePatterns(
[
/\//,
combinePatterns(
[
/[-+a-z0-9!*';:=,.$/%[\]_~@|&]*/,
/[-+a-z0-9/]/, // Valid ending chars
],
{
match: '*',
nonCapture: true,
},
),
],
{
capture: true,
match: '?',
},
[
/\//,
combinePatterns(
[
/[-+a-z0-9!*';:=,.$/%[\]_~@|&]*/,
/[-+a-z0-9/]/, // Valid ending chars
],
{
match: '*',
nonCapture: true,
},
),
],
{
capture: true,
match: '?',
},
);
export const URL_QUERY = combinePatterns(
[
/\?/,
combinePatterns(
[
VALID_PATH_CHARS,
/[a-z0-9_&=]/, // Valid ending chars
],
{
match: '?',
nonCapture: true,
},
),
],
{
capture: true,
match: '?',
},
[
/\?/,
combinePatterns(
[
VALID_PATH_CHARS,
/[a-z0-9_&=]/, // Valid ending chars
],
{
match: '?',
nonCapture: true,
},
),
],
{
capture: true,
match: '?',
},
);
export const URL_FRAGMENT = combinePatterns(
[
/#/,
combinePatterns(
[
VALID_PATH_CHARS,
/[a-z0-9]/, // Valid ending chars
],
{
match: '?',
nonCapture: true,
},
),
],
{
capture: true,
match: '?',
},
[
/#/,
combinePatterns(
[
VALID_PATH_CHARS,
/[a-z0-9]/, // Valid ending chars
],
{
match: '?',
nonCapture: true,
},
),
],
{
capture: true,
match: '?',
},
);
export const URL_PATTERN = combinePatterns(
[URL_SCHEME, URL_AUTH, URL_HOST, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT],
{
flags: 'i',
},
[URL_SCHEME, URL_AUTH, URL_HOST, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT],
{
flags: 'i',
},
);

@@ -132,23 +132,40 @@

export const IP_V4 = combinePatterns([IP_V4_PART, IP_V4_PART, IP_V4_PART, IP_V4_PART], {
capture: true,
join: '\\.',
capture: true,
join: '\\.',
});
export const IP_PATTERN = combinePatterns(
[URL_SCHEME, URL_AUTH, IP_V4, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT],
{
flags: 'i',
},
[URL_SCHEME, URL_AUTH, IP_V4, URL_PORT, URL_PATH, URL_QUERY, URL_FRAGMENT],
{
flags: 'i',
},
);
const NON_LATIN = [
// Chinese
/[\d_\u4E00-\u9FFF-]+/,
// Japanese
/[\d_\u3000-\u30FF-]+/,
// Korean
/[\d_\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uAC00-\uD7FF-]+/,
// Thai
/[\d_\u0E00-\u0E7F-]+/,
// Russian, Ukrainian
// eslint-disable-next-line no-misleading-character-class
/[\d_a-z\u0400-\u052F\u1C80-\u1C8F\u2DE0-\u2DFF\uA640-\uA69F-]+/,
// Latin based
/[\d_a-z\u0080-\u00FF\u0100-\u017F\u0180-\u024F-]+/,
];
export const HASHTAG_PATTERN = combinePatterns(
[
/#/,
combinePatterns([VALID_ALNUM_CHARS, /[-a-z0-9_]*/], {
capture: true,
}),
],
{
flags: 'i',
},
[
/#/,
combinePatterns(NON_LATIN, {
capture: true,
join: '|',
}),
],
{
flags: 'i',
},
);

@@ -159,11 +176,11 @@

export const EMAIL_USERNAME = combinePatterns(
[VALID_ALNUM_CHARS, EMAIL_USERNAME_PART, VALID_ALNUM_CHARS],
{
capture: true,
},
[VALID_ALNUM_CHARS, EMAIL_USERNAME_PART, VALID_ALNUM_CHARS],
{
capture: true,
},
);
export const EMAIL_PATTERN = combinePatterns([EMAIL_USERNAME, URL_HOST], {
flags: 'i',
join: '@',
flags: 'i',
join: '@',
});

@@ -177,281 +194,281 @@

export const TOP_LEVEL_TLDS = [
// Original
'com',
'org',
'net',
'int',
'edu',
'gov',
'mil',
// Sponsored
'aero',
'asia',
'biz',
'cat',
'coop',
'jobs',
'mobi',
'museum',
'post',
'tel',
'travel',
'xxx',
// Misc
'arpa',
'test',
// Countries
'ac', // Ascension Island
'ad', // Andorra
'ae', // United Arab Emirates
'af', // Afghanistan
'ag', // Antigua and Barbuda
'ai', // Anguilla
'al', // Albania
'am', // Armenia
'an', // Netherlands Antilles
'ao', // Angola
'aq', // Antarctica
'ar', // Argentina
'as', // American Samoa
'at', // Austria
'au', // Australia
'aw', // Aruba
'ax', // Aland Islands
'az', // Azerbaijan
'ba', // Bosnia and Herzegovina
'bb', // Barbados
'bd', // Bangladesh
'be', // Belgium
'bf', // Burkina Faso
'bg', // Bulgaria
'bh', // Bahrain
'bi', // Burundi
'bj', // Benin
'bl', // Saint Barthelemy
'bm', // Bermuda
'bn', // Brunei Darussalam
'bo', // Bolivia
'bq', // Bonaire, Sint Eustatius and Saba
'br', // Brazil
'bs', // Bahamas
'bt', // Bhutan
'bv', // Bouvet Island
'bw', // Botswana
'by', // Belarus
'bz', // Belize
'ca', // Canada
'cc', // Cocos (Keeling) Islands
'cd', // Congo, The Democratic Republic of the
'cf', // Central African Republic
'cg', // Congo
'ch', // Switzerland
'ci', // Cote d'Ivoire
'ck', // Cook Islands
'cl', // Chile
'cm', // Cameroon
'cn', // China
'co', // Colombia
'cr', // Costa Rica
'cu', // Cuba
'cv', // Cape Verde
'cw', // CuraƧao
'cx', // Christmas Island
'cy', // Cyprus
'cz', // Czech Republic
'de', // Germany
'dj', // Djibouti
'dk', // Denmark
'dm', // Dominica
'do', // Dominican Republic
'dz', // Algeria
'ec', // Ecuador
'ee', // Estonia
'eg', // Egypt
'eh', // Western Sahara
'er', // Eritrea
'es', // Spain
'et', // Ethiopia
'eu', // European Union
'fi', // Finland
'fj', // Fiji
'fk', // Falkland Islands (Malvinas)
'fm', // Micronesia, Federated States of
'fo', // Faroe Islands
'fr', // France
'ga', // Gabon
'gb', // United Kingdom
'gd', // Grenada
'ge', // Georgia
'gf', // French Guiana
'gg', // Guernsey
'gh', // Ghana
'gi', // Gibraltar
'gl', // Greenland
'gm', // Gambia
'gn', // Guinea
'gp', // Guadeloupe
'gq', // Equatorial Guinea
'gr', // Greece
'gs', // South Georgia and the South Sandwich Islands
'gt', // Guatemala
'gu', // Guam
'gw', // Guinea-Bissau
'gy', // Guyana
'hk', // Hong Kong
'hm', // Heard Island and McDonald Islands
'hn', // Honduras
'hr', // Croatia
'ht', // Haiti
'hu', // Hungary
'id', // Indonesia
'ie', // Ireland
'il', // Israel
'im', // Isle of Man
'in', // India
'io', // British Indian Ocean Territory
'iq', // Iraq
'ir', // Iran, Islamic Republic of
'is', // Iceland
'it', // Italy
'je', // Jersey
'jm', // Jamaica
'jo', // Jordan
'jp', // Japan
'ke', // Kenya
'kg', // Kyrgyzstan
'kh', // Cambodia
'ki', // Kiribati
'km', // Comoros
'kn', // Saint Kitts and Nevis
'kp', // Korea, Democratic People's Republic of
'kr', // Korea, Republic of
'kw', // Kuwait
'ky', // Cayman Islands
'kz', // Kazakhstan
'la', // Lao People's Democratic Republic
'lb', // Lebanon
'lc', // Saint Lucia
'li', // Liechtenstein
'lk', // Sri Lanka
'lr', // Liberia
'ls', // Lesotho
'lt', // Lithuania
'lu', // Luxembourg
'lv', // Latvia
'ly', // Libyan Arab Jamahiriya
'ma', // Morocco
'mc', // Monaco
'md', // Moldova, Republic of
'me', // Montenegro
'mf', // Saint Martin (French part)
'mg', // Madagascar
'mh', // Marshall Islands
'mk', // Macedonia, The Former Yugoslav Republic of
'ml', // Mali
'mm', // Myanmar
'mn', // Mongolia
'mo', // Macao
'mp', // Northern Mariana Islands
'mq', // Martinique
'mr', // Mauritania
'ms', // Montserrat
'mt', // Malta
'mu', // Mauritius
'mv', // Maldives
'mw', // Malawi
'mx', // Mexico
'my', // Malaysia
'mz', // Mozambique
'na', // Namibia
'nc', // New Caledonia
'ne', // Niger
'nf', // Norfolk Island
'ng', // Nigeria
'ni', // Nicaragua
'nl', // Netherlands
'no', // Norway
'np', // Nepal
'nr', // Nauru
'nu', // Niue
'nz', // New Zealand
'om', // Oman
'pa', // Panama
'pe', // Peru
'pf', // French Polynesia
'pg', // Papua New Guinea
'ph', // Philippines
'pk', // Pakistan
'pl', // Poland
'pm', // Saint Pierre and Miquelon
'pn', // Pitcairn
'pr', // Puerto Rico
'ps', // Palestinian Territory, Occupied
'pt', // Portugal
'pw', // Palau
'py', // Paraguay
'qa', // Qatar
're', // Reunion
'ro', // Romania
'rs', // Serbia
'ru', // Russian Federation
'rw', // Rwanda
'sa', // Saudi Arabia
'sb', // Solomon Islands
'sc', // Seychelles
'sd', // Sudan
'se', // Sweden
'sg', // Singapore
'sh', // Saint Helena
'si', // Slovenia
'sj', // Svalbard and Jan Mayen
'sk', // Slovakia
'sl', // Sierra Leone
'sm', // San Marino
'sn', // Senegal
'so', // Somalia
'sr', // Suriname
'st', // Sao Tome and Principe
'su', // Soviet Union (being phased out)
'sv', // El Salvador
'sx', // Sint Maarten (Dutch part)
'sy', // Syrian Arab Republic
'sz', // Swaziland
'tc', // Turks and Caicos Islands
'td', // Chad
'tf', // French Southern Territories
'tg', // Togo
'th', // Thailand
'tj', // Tajikistan
'tk', // Tokelau
'tl', // Timor-Leste
'tm', // Turkmenistan
'tn', // Tunisia
'to', // Tonga
'tp', // Portuguese Timor (being phased out)
'tr', // Turkey
'tt', // Trinidad and Tobago
'tv', // Tuvalu
'tw', // Taiwan, Province of China
'tz', // Tanzania, United Republic of
'ua', // Ukraine
'ug', // Uganda
'uk', // United Kingdom
'um', // United States Minor Outlying Islands
'us', // United States
'uy', // Uruguay
'uz', // Uzbekistan
'va', // Holy See (Vatican City State)
'vc', // Saint Vincent and the Grenadines
've', // Venezuela, Bolivarian Republic of
'vg', // Virgin Islands, British
'vi', // Virgin Islands, U.S.
'vn', // Viet Nam
'vu', // Vanuatu
'wf', // Wallis and Futuna
'ws', // Samoa
'ye', // Yemen
'yt', // Mayotte
'za', // South Africa
'zm', // Zambia
'zw', // Zimbabwe
// Original
'com',
'org',
'net',
'int',
'edu',
'gov',
'mil',
// Sponsored
'aero',
'asia',
'biz',
'cat',
'coop',
'jobs',
'mobi',
'museum',
'post',
'tel',
'travel',
'xxx',
// Misc
'arpa',
'test',
// Countries
'ac', // Ascension Island
'ad', // Andorra
'ae', // United Arab Emirates
'af', // Afghanistan
'ag', // Antigua and Barbuda
'ai', // Anguilla
'al', // Albania
'am', // Armenia
'an', // Netherlands Antilles
'ao', // Angola
'aq', // Antarctica
'ar', // Argentina
'as', // American Samoa
'at', // Austria
'au', // Australia
'aw', // Aruba
'ax', // Aland Islands
'az', // Azerbaijan
'ba', // Bosnia and Herzegovina
'bb', // Barbados
'bd', // Bangladesh
'be', // Belgium
'bf', // Burkina Faso
'bg', // Bulgaria
'bh', // Bahrain
'bi', // Burundi
'bj', // Benin
'bl', // Saint Barthelemy
'bm', // Bermuda
'bn', // Brunei Darussalam
'bo', // Bolivia
'bq', // Bonaire, Sint Eustatius and Saba
'br', // Brazil
'bs', // Bahamas
'bt', // Bhutan
'bv', // Bouvet Island
'bw', // Botswana
'by', // Belarus
'bz', // Belize
'ca', // Canada
'cc', // Cocos (Keeling) Islands
'cd', // Congo, The Democratic Republic of the
'cf', // Central African Republic
'cg', // Congo
'ch', // Switzerland
'ci', // Cote d'Ivoire
'ck', // Cook Islands
'cl', // Chile
'cm', // Cameroon
'cn', // China
'co', // Colombia
'cr', // Costa Rica
'cu', // Cuba
'cv', // Cape Verde
'cw', // CuraƧao
'cx', // Christmas Island
'cy', // Cyprus
'cz', // Czech Republic
'de', // Germany
'dj', // Djibouti
'dk', // Denmark
'dm', // Dominica
'do', // Dominican Republic
'dz', // Algeria
'ec', // Ecuador
'ee', // Estonia
'eg', // Egypt
'eh', // Western Sahara
'er', // Eritrea
'es', // Spain
'et', // Ethiopia
'eu', // European Union
'fi', // Finland
'fj', // Fiji
'fk', // Falkland Islands (Malvinas)
'fm', // Micronesia, Federated States of
'fo', // Faroe Islands
'fr', // France
'ga', // Gabon
'gb', // United Kingdom
'gd', // Grenada
'ge', // Georgia
'gf', // French Guiana
'gg', // Guernsey
'gh', // Ghana
'gi', // Gibraltar
'gl', // Greenland
'gm', // Gambia
'gn', // Guinea
'gp', // Guadeloupe
'gq', // Equatorial Guinea
'gr', // Greece
'gs', // South Georgia and the South Sandwich Islands
'gt', // Guatemala
'gu', // Guam
'gw', // Guinea-Bissau
'gy', // Guyana
'hk', // Hong Kong
'hm', // Heard Island and McDonald Islands
'hn', // Honduras
'hr', // Croatia
'ht', // Haiti
'hu', // Hungary
'id', // Indonesia
'ie', // Ireland
'il', // Israel
'im', // Isle of Man
'in', // India
'io', // British Indian Ocean Territory
'iq', // Iraq
'ir', // Iran, Islamic Republic of
'is', // Iceland
'it', // Italy
'je', // Jersey
'jm', // Jamaica
'jo', // Jordan
'jp', // Japan
'ke', // Kenya
'kg', // Kyrgyzstan
'kh', // Cambodia
'ki', // Kiribati
'km', // Comoros
'kn', // Saint Kitts and Nevis
'kp', // Korea, Democratic People's Republic of
'kr', // Korea, Republic of
'kw', // Kuwait
'ky', // Cayman Islands
'kz', // Kazakhstan
'la', // Lao People's Democratic Republic
'lb', // Lebanon
'lc', // Saint Lucia
'li', // Liechtenstein
'lk', // Sri Lanka
'lr', // Liberia
'ls', // Lesotho
'lt', // Lithuania
'lu', // Luxembourg
'lv', // Latvia
'ly', // Libyan Arab Jamahiriya
'ma', // Morocco
'mc', // Monaco
'md', // Moldova, Republic of
'me', // Montenegro
'mf', // Saint Martin (French part)
'mg', // Madagascar
'mh', // Marshall Islands
'mk', // Macedonia, The Former Yugoslav Republic of
'ml', // Mali
'mm', // Myanmar
'mn', // Mongolia
'mo', // Macao
'mp', // Northern Mariana Islands
'mq', // Martinique
'mr', // Mauritania
'ms', // Montserrat
'mt', // Malta
'mu', // Mauritius
'mv', // Maldives
'mw', // Malawi
'mx', // Mexico
'my', // Malaysia
'mz', // Mozambique
'na', // Namibia
'nc', // New Caledonia
'ne', // Niger
'nf', // Norfolk Island
'ng', // Nigeria
'ni', // Nicaragua
'nl', // Netherlands
'no', // Norway
'np', // Nepal
'nr', // Nauru
'nu', // Niue
'nz', // New Zealand
'om', // Oman
'pa', // Panama
'pe', // Peru
'pf', // French Polynesia
'pg', // Papua New Guinea
'ph', // Philippines
'pk', // Pakistan
'pl', // Poland
'pm', // Saint Pierre and Miquelon
'pn', // Pitcairn
'pr', // Puerto Rico
'ps', // Palestinian Territory, Occupied
'pt', // Portugal
'pw', // Palau
'py', // Paraguay
'qa', // Qatar
're', // Reunion
'ro', // Romania
'rs', // Serbia
'ru', // Russian Federation
'rw', // Rwanda
'sa', // Saudi Arabia
'sb', // Solomon Islands
'sc', // Seychelles
'sd', // Sudan
'se', // Sweden
'sg', // Singapore
'sh', // Saint Helena
'si', // Slovenia
'sj', // Svalbard and Jan Mayen
'sk', // Slovakia
'sl', // Sierra Leone
'sm', // San Marino
'sn', // Senegal
'so', // Somalia
'sr', // Suriname
'st', // Sao Tome and Principe
'su', // Soviet Union (being phased out)
'sv', // El Salvador
'sx', // Sint Maarten (Dutch part)
'sy', // Syrian Arab Republic
'sz', // Swaziland
'tc', // Turks and Caicos Islands
'td', // Chad
'tf', // French Southern Territories
'tg', // Togo
'th', // Thailand
'tj', // Tajikistan
'tk', // Tokelau
'tl', // Timor-Leste
'tm', // Turkmenistan
'tn', // Tunisia
'to', // Tonga
'tp', // Portuguese Timor (being phased out)
'tr', // Turkey
'tt', // Trinidad and Tobago
'tv', // Tuvalu
'tw', // Taiwan, Province of China
'tz', // Tanzania, United Republic of
'ua', // Ukraine
'ug', // Uganda
'uk', // United Kingdom
'um', // United States Minor Outlying Islands
'us', // United States
'uy', // Uruguay
'uz', // Uzbekistan
'va', // Holy See (Vatican City State)
'vc', // Saint Vincent and the Grenadines
've', // Venezuela, Bolivarian Republic of
'vg', // Virgin Islands, British
'vi', // Virgin Islands, U.S.
'vn', // Viet Nam
'vu', // Vanuatu
'wf', // Wallis and Futuna
'ws', // Samoa
'ye', // Yemen
'yt', // Mayotte
'za', // South Africa
'zm', // Zambia
'zw', // Zimbabwe
];
import React from 'react';
import { ChildrenNode, Matcher, MatchResponse, Node } from 'interweave';
import { EMAIL_PATTERN } from './constants';
import Email from './Email';
import { Email } from './Email';
import { EmailProps } from './types';

@@ -9,20 +9,20 @@

export default class EmailMatcher extends Matcher<EmailProps> {
replaceWith(children: ChildrenNode, props: EmailProps): Node {
return React.createElement(Email, props, children);
}
export class EmailMatcher extends Matcher<EmailProps> {
replaceWith(children: ChildrenNode, props: EmailProps): Node {
return React.createElement(Email, props, children);
}
asTag(): string {
return 'a';
}
asTag(): string {
return 'a';
}
match(string: string): MatchResponse<EmailMatch> | null {
return this.doMatch(string, EMAIL_PATTERN, (matches) => ({
email: matches[0],
emailParts: {
host: matches[2],
username: matches[1],
},
}));
}
match(string: string): MatchResponse<EmailMatch> | null {
return this.doMatch(string, EMAIL_PATTERN, (matches) => ({
email: matches[0],
emailParts: {
host: matches[2],
username: matches[1],
},
}));
}
}
import React from 'react';
import { ChildrenNode, Matcher, MatchResponse, Node } from 'interweave';
import { HASHTAG_PATTERN } from './constants';
import Hashtag from './Hashtag';
import { Hashtag } from './Hashtag';
import { HashtagProps } from './types';

@@ -9,16 +9,16 @@

export default class HashtagMatcher extends Matcher<HashtagProps> {
replaceWith(children: ChildrenNode, props: HashtagProps): Node {
return React.createElement(Hashtag, props, children);
}
export class HashtagMatcher extends Matcher<HashtagProps> {
replaceWith(children: ChildrenNode, props: HashtagProps): Node {
return React.createElement(Hashtag, props, children);
}
asTag(): string {
return 'a';
}
asTag(): string {
return 'a';
}
match(string: string): MatchResponse<HashtagMatch> | null {
return this.doMatch(string, HASHTAG_PATTERN, (matches) => ({
hashtag: matches[0],
}));
}
match(string: string): MatchResponse<HashtagMatch> | null {
return this.doMatch(string, HASHTAG_PATTERN, (matches) => ({
hashtag: matches[0],
}));
}
}
/**
* @copyright 2016-2019, Miles Johnson
* @copyright 2021, Miles Johnson
* @license https://opensource.org/licenses/MIT
*/
import Email from './Email';
import EmailMatcher from './EmailMatcher';
import Hashtag from './Hashtag';
import HashtagMatcher from './HashtagMatcher';
import IpMatcher from './IpMatcher';
import Link from './Link';
import Url from './Url';
import UrlMatcher from './UrlMatcher';
export { Email, EmailMatcher, Hashtag, HashtagMatcher, IpMatcher, Link, Url, UrlMatcher };
export * from './constants';
export * from './Email';
export * from './EmailMatcher';
export * from './Hashtag';
export * from './HashtagMatcher';
export * from './IpMatcher';
export * from './Link';
export * from './types';
export * from './Url';
export * from './UrlMatcher';

@@ -5,24 +5,24 @@ import React from 'react';

import { UrlMatcherOptions, UrlProps } from './types';
import UrlMatcher, { UrlMatch } from './UrlMatcher';
import { UrlMatch, UrlMatcher } from './UrlMatcher';
export default class IpMatcher extends UrlMatcher {
constructor(
name: string,
options?: UrlMatcherOptions,
factory?: React.ComponentType<UrlProps> | null,
) {
super(
name,
{
...options,
// IPs dont have TLDs
validateTLD: false,
},
factory,
);
}
export class IpMatcher extends UrlMatcher {
constructor(
name: string,
options?: UrlMatcherOptions,
factory?: React.ComponentType<UrlProps> | null,
) {
super(
name,
{
...options,
// IPs dont have TLDs
validateTLD: false,
},
factory,
);
}
match(string: string): MatchResponse<UrlMatch> | null {
return this.doMatch(string, IP_PATTERN, this.handleMatches);
}
override match(string: string): MatchResponse<UrlMatch> | null {
return this.doMatch(string, IP_PATTERN, this.handleMatches);
}
}

@@ -5,43 +5,43 @@ import React from 'react';

export interface LinkProps {
children: React.ReactNode;
href: string;
key?: number | string;
newWindow?: boolean;
onClick?: () => null | void;
children: React.ReactNode;
href: string;
key?: number | string;
newWindow?: boolean;
onClick?: () => null | void;
}
export interface EmailProps extends Partial<LinkProps> {
children: ChildrenNode;
email: string;
emailParts: {
host: string;
username: string;
};
children: ChildrenNode;
email: string;
emailParts: {
host: string;
username: string;
};
}
export interface HashtagProps extends Partial<LinkProps> {
children: ChildrenNode;
encodeHashtag?: boolean;
hashtag: string;
hashtagUrl?: string | ((hashtag: string) => string);
preserveHash?: boolean;
children: ChildrenNode;
encodeHashtag?: boolean;
hashtag: string;
hashtagUrl?: string | ((hashtag: string) => string);
preserveHash?: boolean;
}
export interface UrlProps extends Partial<LinkProps> {
children: ChildrenNode;
url: string;
urlParts: {
auth: string;
fragment: string;
host: string;
path: string;
port: number | string;
query: string;
scheme: string;
};
children: ChildrenNode;
url: string;
urlParts: {
auth: string;
fragment: string;
host: string;
path: string;
port: number | string;
query: string;
scheme: string;
};
}
export interface UrlMatcherOptions {
customTLDs?: string[];
validateTLD?: boolean;
customTLDs?: string[];
validateTLD?: boolean;
}

@@ -5,69 +5,69 @@ import React from 'react';

import { UrlMatcherOptions, UrlProps } from './types';
import Url from './Url';
import { Url } from './Url';
export type UrlMatch = Pick<UrlProps, 'url' | 'urlParts'>;
export default class UrlMatcher extends Matcher<UrlProps, UrlMatcherOptions> {
constructor(
name: string,
options?: UrlMatcherOptions,
factory?: React.ComponentType<UrlProps> | null,
) {
super(
name,
{
customTLDs: [],
validateTLD: true,
...options,
},
factory,
);
}
export class UrlMatcher extends Matcher<UrlProps, UrlMatcherOptions> {
constructor(
name: string,
options?: UrlMatcherOptions,
factory?: React.ComponentType<UrlProps> | null,
) {
super(
name,
{
customTLDs: [],
validateTLD: true,
...options,
},
factory,
);
}
replaceWith(children: ChildrenNode, props: UrlProps): Node {
return React.createElement(Url, props, children);
}
replaceWith(children: ChildrenNode, props: UrlProps): Node {
return React.createElement(Url, props, children);
}
asTag(): string {
return 'a';
}
asTag(): string {
return 'a';
}
match(string: string): MatchResponse<UrlMatch> | null {
const response = this.doMatch(string, URL_PATTERN, this.handleMatches);
match(string: string): MatchResponse<UrlMatch> | null {
const response = this.doMatch(string, URL_PATTERN, this.handleMatches);
// False positives with URL auth scheme
if (response?.match.match(EMAIL_DISTINCT_PATTERN)) {
response.valid = false;
}
// False positives with URL auth scheme
if (response?.match.match(EMAIL_DISTINCT_PATTERN)) {
response.valid = false;
}
if (response?.valid && this.options.validateTLD) {
const { host } = (response.urlParts as unknown) as UrlProps['urlParts'];
const validList = TOP_LEVEL_TLDS.concat(this.options.customTLDs || []);
const tld = host.slice(host.lastIndexOf('.') + 1).toLowerCase();
if (response?.valid && this.options.validateTLD) {
const { host } = (response.urlParts as unknown) as UrlProps['urlParts'];
const validList = [...TOP_LEVEL_TLDS, ...(this.options.customTLDs ?? [])];
const tld = host.slice(host.lastIndexOf('.') + 1).toLowerCase();
if (!validList.includes(tld)) {
return null;
}
}
if (!validList.includes(tld)) {
return null;
}
}
return response;
}
return response;
}
/**
* Package the matched response.
*/
handleMatches(matches: string[]): UrlMatch {
return {
url: matches[0],
urlParts: {
auth: matches[2] ? matches[2].slice(0, -1) : '',
fragment: matches[7] || '',
host: matches[3],
path: matches[5] || '',
port: matches[4] ? matches[4] : '',
query: matches[6] || '',
scheme: matches[1] ? matches[1].replace('://', '') : 'http',
},
};
}
/**
* Package the matched response.
*/
handleMatches(matches: string[]): UrlMatch {
return {
url: matches[0],
urlParts: {
auth: matches[2] ? matches[2].slice(0, -1) : '',
fragment: matches[7] || '',
host: matches[3],
path: matches[5] || '',
port: matches[4] ? matches[4] : '',
query: matches[6] || '',
scheme: matches[1] ? matches[1].replace('://', '') : 'http',
},
};
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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