Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const replacements = {
'<': '<',
'>': '>',
'"': '"',
};
function normhtml(str) {
// Like escapehtml but doesn't escape & since we don't want to have
// to decode and then reencode.
return str.replace(/[<>"]/g, (chr) => replacements[chr]);
}
// A registry name should end in a TLD. We sort TLDs so that the RegExp greedily matches
// the longest TLD: e.g. .community should come before .com.
const REG_NAME = String.raw`(?:[a-z0-9\-_~!$&'()*+,;=%]+[.])+(?:${ tlds.sort(descLength).join('|') })[.]?`;
// TODO: range restrict
// eslint-disable-next-line id-match
const IPV4 = String.raw`\d+(?:\.\d+){3}(?=[/?#]|:\d)`;
// TODO: count hex digits properly.
// eslint-disable-next-line id-match
const IPV6 = String.raw`\[(?!\])(?:[0-9a-f]+(?:[:][0-9a-f]+)*)?(?:[:][:](?:[0-9a-f]+(?:[:][0-9a-f]+)*))?\]`;
const PROTOCOL_REGEX = String.raw`\b([a-z][a-z0-9+\-.]*):`;
const PROTOCOL_PATTERN = new RegExp(`^${ PROTOCOL_REGEX }`, 'i');
const AUTHORITY_REGEX = String.raw`[^/:?#\s<>!,;]*`;
const AUTHORITY_PATTERN = new RegExp(`^(?:[^:/#?]*:)?//(${ AUTHORITY_REGEX })`);
function process_link(raw_data) {
const DESCRIPTION_PREFIX = ' - ';
validate(!!raw_data.url, "URL shouldn't be empty");
validate(!!raw_data.texts.inside, "URL text shouldn't be empty");
if( ! normalize_url.is_url(raw_data.url) ) {
return null;
}
// validate(raw_data.texts.before==='', "URL shouldn't be preceded by any text");
if( raw_data.texts.before!=='' ) {
return null;
}
validate(validator.isURL(raw_data.url,{allow_underscores: true}), "Doesn't seem to be an URL: `"+raw_data.url+"`");
const resource_url = raw_data.url;
const dn = normalize_url(resource_url).split('/')[0];
validate(validator.isFQDN(dn), "Doesn't seem to be a valid domain: `"+dn+"`");
validate(tlds.includes(dn.split('.').slice(-1)[0]), "Doesn't seem to be a valid TLD for: `"+dn+"`");
const title = raw_data.texts.inside;
let description = raw_data.texts.after;
if( description.startsWith(DESCRIPTION_PREFIX) ) {
description = description.slice(DESCRIPTION_PREFIX.length);
}
delete raw_data;
return {
resource_url,
title,
description,
};
function validate(passed, msg){
private buildUrl(query: string) {
// See if they have started with a web scheme
if (/^https?:\/\/\w+/.test(query)) {
return query;
}
// See if they have ended with a valid TLD
if (tlds.some(tld => query.endsWith(`.${tld}`))) {
return `https://${query}`;
}
// Probably searching then
const searchEngine =
engines.find(engine => engine.key === this.props.data!.searchEngine) ||
engines[0];
return searchEngine.search_url.replace('{searchTerms}', query);
}
export function buildUrl(query: string, engineUrl: string) {
// See if they have started with a web scheme
if (/^https?:\/\/\w+/.test(query)) {
return query;
}
// See if they have ended with a valid TLD
if (tlds.some(tld => query.endsWith(`.${tld}`))) {
return `https://${query}`;
}
// Probably searching then
return engineUrl.replace('{searchTerms}', encodeURIComponent(query));
}
for (i = 1; ; i++) {
if (str[i] !== String.fromCharCode(str[i - 1].charCodeAt(0) + 1)) {
if (i < 3) {
ranges.push(str.slice(0, i));
} else {
ranges.push(str[0] + '-' + str[i - 1]);
}
str = str.slice(i);
break;
}
}
}
return '[' + ranges.join('') + ']';
}
var tlds = require('tlds').filter(name => /^[a-z]{2}$/.test(name)).sort();
//
// group by first letter
//
var result = [];
'abcdefghijklmnopqrstuvwxyz'.split('').forEach(letter => {
var list = tlds.filter(name => name[0] === letter);
if (!list.length) { return; }
if (list.length < 2) {
result = result.concat(list);
return;
}
import tlds from 'tlds';
// Reusables
const validTlds = tlds.concat(['local', 'dev']).join('|');
const escapeChar = `\\`;
const notWhitespaceCommaDoubleQuoteOrDot = `[^${escapeChar}s,"]`;
const dot = `${escapeChar}.`;
const hostnameChars = `[a-z0-9]`;
const number = `[0-9]`;
const endingChars = `${dot}?([${escapeChar}s<>",]|$)`;
// Sections
const optionalScheme = `(([a-z]+:)?//)?`;
const hostname = `(((${hostnameChars}-*)*${hostnameChars}+)${dot})+(${validTlds})`;
const ip = `(${number}{1,3}${dot}){3}${number}{1,3}`;
const optionalPortNumber = `(:${number}+)?`;
const optionalSlash = `(${escapeChar}/(${notWhitespaceCommaDoubleQuoteOrDot}*)?)?`;
const endsWithButDontMatch = `(?=${endingChars})`;
// Build
function validate_normalized_url(val, {Thing}) {
const dn = val.split('/')[0];
const dn_msg = "Domain name `"+dn+"`"+(dn!==val?" (of `"+val+"`)":"");
if( ! dn.includes('.') ) {
throw new Thing.ValidationError(dn_msg+" is missing a dot. The domain name needs to have at least one dot like in `example.org`.");
}
if( ! validator.isFQDN(dn) ) {
throw new Thing.ValidationError(dn_msg+" doesn't seem to exist.");
}
const tld = dn.split('.').slice(-1)[0];
if( ! tlds.includes(tld) ) {
throw new Thing.ValidationError("The root `"+tld+"` (in the domain name `"+dn+"`"+(dn!==val?(" of `"+val+"`"):"")+") doesn't seem to exist.");
}
if( val.endsWith('/') ) {
return false;
}
return true;
}
return matches.reduce((urls, match) => {
if (!protocolRegex.test(match)) {
match = `https://${match}`;
}
let matchUrl: url.URL;
try {
matchUrl = new url.URL(match);
} catch (e) {
return urls;
}
const hostnameParts = matchUrl.hostname.split(".");
const tld = hostnameParts[hostnameParts.length - 1];
if (tlds.includes(tld)) {
urls.push(matchUrl);
}
return urls;
}, []);
}
const validateTld = email => {
let tld = email
.split("@")
.pop()
.split(".")
.pop()
.toLowerCase();
if (tlds.indexOf(tld) === -1) return tld;
else return true;
};
export default (_opts) => {
const opts = Object.assign({ strict: true }, _opts);
const protocol = `(?:(?:[a-z]+:)?//)${opts.strict ? '' : '?'}`;
const auth = '(?:\\S+(?::\\S*)?@)?';
const ip = ipRegex.v4().source;
const host = '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)';
const domain = '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*';
const tld = `(?:\\.${opts.strict ? '(?:[a-z\\u00a1-\\uffff]{2,})' : `(?:${tlds.sort((a, b) => b.length - a.length).join('|')})`})\\.?`;
const port = '(?::\\d{2,5})?';
const path = '(?:[/?#][^\\s"]*)?';
const regex = `(?:${protocol}|www\\.)${auth}(?:localhost|${ip}|${host}${domain}${tld})${port}${path}`;
return opts.exact ? new RegExp(`(?:^${regex}$)`, 'i') : new RegExp(regex, 'ig');
};