mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Updated Autolinker library (Closes #532)
This commit is contained in:
parent
45fc261b28
commit
f817a680a2
15 changed files with 3145 additions and 869 deletions
|
|
@ -17,8 +17,7 @@
|
||||||
|
|
||||||
this.sBase = '#/';
|
this.sBase = '#/';
|
||||||
this.sServer = './?';
|
this.sServer = './?';
|
||||||
this.sSubQuery = '&s=/';
|
|
||||||
this.sSubSubQuery = '&ss=/';
|
|
||||||
this.sVersion = Settings.settingsGet('Version');
|
this.sVersion = Settings.settingsGet('Version');
|
||||||
this.sSpecSuffix = Settings.settingsGet('AuthAccountHash') || '0';
|
this.sSpecSuffix = Settings.settingsGet('AuthAccountHash') || '0';
|
||||||
this.sWebPrefix = Settings.settingsGet('WebPath') || '';
|
this.sWebPrefix = Settings.settingsGet('WebPath') || '';
|
||||||
|
|
@ -26,6 +25,14 @@
|
||||||
this.sStaticPrefix = this.sVersionPrefix + 'static/';
|
this.sStaticPrefix = this.sVersionPrefix + 'static/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
Links.prototype.subQueryPrefix = function ()
|
||||||
|
{
|
||||||
|
return '&q[]=';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
@ -48,7 +55,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.attachmentDownload = function (sDownload)
|
Links.prototype.attachmentDownload = function (sDownload)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/Download/' + this.sSubSubQuery + sDownload;
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/Download/' + this.subQueryPrefix() + '/' + sDownload;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -57,7 +64,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.attachmentPreview = function (sDownload)
|
Links.prototype.attachmentPreview = function (sDownload)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/View/' + this.sSubSubQuery + sDownload;
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/View/' + this.subQueryPrefix() + '/' + sDownload;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -66,7 +73,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.attachmentThumbnailPreview = function (sDownload)
|
Links.prototype.attachmentThumbnailPreview = function (sDownload)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/ViewThumbnail/' + this.sSubSubQuery + sDownload;
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ViewThumbnail/' + this.subQueryPrefix() + '/' + sDownload;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -75,7 +82,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.attachmentPreviewAsPlain = function (sDownload)
|
Links.prototype.attachmentPreviewAsPlain = function (sDownload)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/ViewAsPlain/' + this.sSubSubQuery + sDownload;
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ViewAsPlain/' + this.subQueryPrefix() + '/' + sDownload;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -84,7 +91,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.attachmentFramed = function (sDownload)
|
Links.prototype.attachmentFramed = function (sDownload)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/FramedView/' + this.sSubSubQuery + sDownload;
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/FramedView/' + this.subQueryPrefix() + '/' + sDownload;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -92,7 +99,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.upload = function ()
|
Links.prototype.upload = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + '/Upload/' + this.sSubQuery + this.sSpecSuffix + '/';
|
return this.sServer + '/Upload/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -100,7 +107,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.uploadContacts = function ()
|
Links.prototype.uploadContacts = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + '/UploadContacts/' + this.sSubQuery + this.sSpecSuffix + '/';
|
return this.sServer + '/UploadContacts/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,7 +115,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.uploadBackground = function ()
|
Links.prototype.uploadBackground = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + '/UploadBackground/' + this.sSubQuery + this.sSpecSuffix + '/';
|
return this.sServer + '/UploadBackground/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,7 +123,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.append = function ()
|
Links.prototype.append = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + '/Append/' + this.sSubQuery + this.sSpecSuffix + '/';
|
return this.sServer + '/Append/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -125,7 +132,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.change = function (sEmail)
|
Links.prototype.change = function (sEmail)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Change/' + this.sSubQuery + this.sSpecSuffix + '/' + Utils.encodeURIComponent(sEmail) + '/';
|
return this.sServer + '/Change/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' + Utils.encodeURIComponent(sEmail) + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -134,7 +141,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.ajax = function (sAdd)
|
Links.prototype.ajax = function (sAdd)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Ajax/' + this.sSubQuery + this.sSpecSuffix + '/' + sAdd;
|
return this.sServer + '/Ajax/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' + sAdd;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -143,7 +150,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.messageViewLink = function (sRequestHash)
|
Links.prototype.messageViewLink = function (sRequestHash)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/ViewAsPlain/' + this.sSubSubQuery + sRequestHash;
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ViewAsPlain/' + this.subQueryPrefix() + '/' + sRequestHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -152,7 +159,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.messageDownloadLink = function (sRequestHash)
|
Links.prototype.messageDownloadLink = function (sRequestHash)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/Download/' + this.sSubSubQuery + sRequestHash;
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/Download/' + this.subQueryPrefix() + '/' + sRequestHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -179,8 +186,8 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.userBackground = function (sHash)
|
Links.prototype.userBackground = function (sHash)
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/UserBackground/' +
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix +
|
||||||
this.sSubSubQuery + sHash;
|
'/UserBackground/' + this.subQueryPrefix() + '/' + sHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -298,7 +305,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.exportContactsVcf = function ()
|
Links.prototype.exportContactsVcf = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/ContactsVcf/';
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ContactsVcf/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -306,7 +313,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.exportContactsCsv = function ()
|
Links.prototype.exportContactsCsv = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + '/Raw/' + this.sSubQuery + this.sSpecSuffix + '/ContactsCsv/';
|
return this.sServer + '/Raw/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/ContactsCsv/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -363,7 +370,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.socialGoogle = function ()
|
Links.prototype.socialGoogle = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + 'SocialGoogle' + ('' !== this.sSpecSuffix ? '/' + this.sSubQuery + this.sSpecSuffix + '/' : '');
|
return this.sServer + 'SocialGoogle' + ('' !== this.sSpecSuffix ? '/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' : '');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -371,7 +378,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.socialTwitter = function ()
|
Links.prototype.socialTwitter = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + 'SocialTwitter' + ('' !== this.sSpecSuffix ? '/' + this.sSubQuery + this.sSpecSuffix + '/' : '');
|
return this.sServer + 'SocialTwitter' + ('' !== this.sSpecSuffix ? '/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' : '');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -379,7 +386,7 @@
|
||||||
*/
|
*/
|
||||||
Links.prototype.socialFacebook = function ()
|
Links.prototype.socialFacebook = function ()
|
||||||
{
|
{
|
||||||
return this.sServer + 'SocialFacebook' + ('' !== this.sSpecSuffix ? '/' + this.sSubQuery + this.sSpecSuffix + '/' : '');
|
return this.sServer + 'SocialFacebook' + ('' !== this.sSpecSuffix ? '/' + this.subQueryPrefix() + '/' + this.sSpecSuffix + '/' : '');
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = new Links();
|
module.exports = new Links();
|
||||||
|
|
|
||||||
|
|
@ -1062,6 +1062,7 @@
|
||||||
*/
|
*/
|
||||||
Utils.findEmailAndLinks = function (sHtml)
|
Utils.findEmailAndLinks = function (sHtml)
|
||||||
{
|
{
|
||||||
|
// return sHtml;
|
||||||
sHtml = Autolinker.link(sHtml, {
|
sHtml = Autolinker.link(sHtml, {
|
||||||
'newWindow': true,
|
'newWindow': true,
|
||||||
'stripPrefix': false,
|
'stripPrefix': false,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
// Utils = require('Common/Utils'),
|
// Utils = require('Common/Utils'),
|
||||||
// Base64 = require('Common/Base64'),
|
// Base64 = require('Common/Base64'),
|
||||||
// Cache = require('Common/Cache'),
|
// Cache = require('Common/Cache'),
|
||||||
|
// Links = require('Common/Links'),
|
||||||
//
|
//
|
||||||
// AppStore = require('Stores/User/App'),
|
// AppStore = require('Stores/User/App'),
|
||||||
// SettingsStore = require('Stores/User/Settings'),
|
// SettingsStore = require('Stores/User/Settings'),
|
||||||
|
|
@ -31,8 +32,6 @@
|
||||||
|
|
||||||
this.messageListSimpleHash = '';
|
this.messageListSimpleHash = '';
|
||||||
this.messageListSimpleCache = null;
|
this.messageListSimpleCache = null;
|
||||||
|
|
||||||
this.sSubSubQuery = '&ss=/';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_.extend(UserAjaxUserPromises.prototype, AbstractAjaxPromises.prototype);
|
_.extend(UserAjaxUserPromises.prototype, AbstractAjaxPromises.prototype);
|
||||||
|
|
@ -123,7 +122,7 @@
|
||||||
// {
|
// {
|
||||||
// return this.abort('Message')
|
// return this.abort('Message')
|
||||||
// .getRequest('Message', fTrigger,
|
// .getRequest('Message', fTrigger,
|
||||||
// this.sSubSubQuery + Base64.urlsafe_encode([
|
// Links.subQueryPrefix() + '/' + Base64.urlsafe_encode([
|
||||||
// sFolderFullNameRaw, iUid,
|
// sFolderFullNameRaw, iUid,
|
||||||
// AppStore.projectHash(),
|
// AppStore.projectHash(),
|
||||||
// AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0'
|
// AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0'
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
Base64 = require('Common/Base64'),
|
Base64 = require('Common/Base64'),
|
||||||
|
|
||||||
Cache = require('Common/Cache'),
|
Cache = require('Common/Cache'),
|
||||||
|
Links = require('Common/Links'),
|
||||||
|
|
||||||
Settings = require('Storage/Settings'),
|
Settings = require('Storage/Settings'),
|
||||||
|
|
||||||
|
|
@ -29,8 +30,6 @@
|
||||||
AbstractAjaxRemote.call(this);
|
AbstractAjaxRemote.call(this);
|
||||||
|
|
||||||
this.oRequests = {};
|
this.oRequests = {};
|
||||||
|
|
||||||
this.sSubSubQuery = '&ss=/';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_.extend(RemoteUserAjax.prototype, AbstractAjaxRemote.prototype);
|
_.extend(RemoteUserAjax.prototype, AbstractAjaxRemote.prototype);
|
||||||
|
|
@ -352,7 +351,7 @@
|
||||||
{
|
{
|
||||||
return this.defaultRequest(fCallback, 'MessageList', {},
|
return this.defaultRequest(fCallback, 'MessageList', {},
|
||||||
'' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout,
|
'' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout,
|
||||||
'MessageList/' + this.sSubSubQuery + Base64.urlsafe_encode([
|
'MessageList/' + Links.subQueryPrefix() + '/' + Base64.urlsafe_encode([
|
||||||
sFolderFullNameRaw,
|
sFolderFullNameRaw,
|
||||||
iOffset,
|
iOffset,
|
||||||
iLimit,
|
iLimit,
|
||||||
|
|
@ -402,7 +401,7 @@
|
||||||
if (Cache.getFolderFromCacheList(sFolderFullNameRaw) && 0 < iUid)
|
if (Cache.getFolderFromCacheList(sFolderFullNameRaw) && 0 < iUid)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Message', {}, null,
|
this.defaultRequest(fCallback, 'Message', {}, null,
|
||||||
'Message/' + this.sSubSubQuery + Base64.urlsafe_encode([
|
'Message/' + Links.subQueryPrefix() + '/' + Base64.urlsafe_encode([
|
||||||
sFolderFullNameRaw,
|
sFolderFullNameRaw,
|
||||||
iUid,
|
iUid,
|
||||||
AppStore.projectHash(),
|
AppStore.projectHash(),
|
||||||
|
|
|
||||||
|
|
@ -372,11 +372,24 @@ class Actions
|
||||||
|
|
||||||
$sQuery = \trim(\trim($sQuery), ' /');
|
$sQuery = \trim(\trim($sQuery), ' /');
|
||||||
|
|
||||||
$sSubQuerty = \trim(\trim($this->Http()->GetQuery('s', '')), ' /');
|
$aSubQuery = $this->Http()->GetQuery('q', null);
|
||||||
$sSubSubQuerty = \trim(\trim($this->Http()->GetQuery('ss', '')), ' /');
|
if (\is_array($aSubQuery))
|
||||||
|
{
|
||||||
|
$aSubQuery = \array_map(function ($sS) {
|
||||||
|
return \trim(\trim($sS), ' /');
|
||||||
|
}, $aSubQuery);
|
||||||
|
|
||||||
$sQuery .= 0 < \strlen($sSubQuerty) ? '/'.$sSubQuerty : '';
|
if (0 < \count($aSubQuery))
|
||||||
$sQuery .= 0 < \strlen($sSubSubQuerty) ? '/'.$sSubSubQuerty : '';
|
{
|
||||||
|
$sQuery .= '/'.\implode('/', $aSubQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// $sSubQuerty = \trim(\trim($this->Http()->GetQuery('s', '')), ' /');
|
||||||
|
// $sSubSubQuerty = \trim(\trim($this->Http()->GetQuery('ss', '')), ' /');
|
||||||
|
//
|
||||||
|
// $sQuery .= 0 < \strlen($sSubQuerty) ? '/'.$sSubQuerty : '';
|
||||||
|
// $sQuery .= 0 < \strlen($sSubSubQuerty) ? '/'.$sSubSubQuerty : '';
|
||||||
|
|
||||||
if ('' === $this->GetSpecAuthToken())
|
if ('' === $this->GetSpecAuthToken())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
478
vendors/Autolinker/Autolinker.js
vendored
478
vendors/Autolinker/Autolinker.js
vendored
|
|
@ -1,24 +1,28 @@
|
||||||
|
(function (root, factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
// AMD. Register as an anonymous module.
|
||||||
|
define([], function () {
|
||||||
|
return (root.returnExportsGlobal = factory());
|
||||||
|
});
|
||||||
|
} else if (typeof exports === 'object') {
|
||||||
|
// Node. Does not work with strict CommonJS, but
|
||||||
|
// only CommonJS-like enviroments that support module.exports,
|
||||||
|
// like Node.
|
||||||
|
module.exports = factory();
|
||||||
|
} else {
|
||||||
|
root['Autolinker'] = factory();
|
||||||
|
}
|
||||||
|
}(this, function () {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Autolinker.js
|
* Autolinker.js
|
||||||
* 0.12.2
|
* 0.15.2
|
||||||
*
|
*
|
||||||
* Copyright(c) 2014 Gregory Jacobs <greg@greg-jacobs.com>
|
* Copyright(c) 2015 Gregory Jacobs <greg@greg-jacobs.com>
|
||||||
* MIT Licensed. http://www.opensource.org/licenses/mit-license.php
|
* MIT Licensed. http://www.opensource.org/licenses/mit-license.php
|
||||||
*
|
*
|
||||||
* https://github.com/gregjacobs/Autolinker.js
|
* https://github.com/gregjacobs/Autolinker.js
|
||||||
*/
|
*/
|
||||||
/*global define, module */
|
|
||||||
( function( root, factory ) {
|
|
||||||
|
|
||||||
if( typeof define === 'function' && define.amd ) {
|
|
||||||
define( factory ); // Define as AMD module if an AMD loader is present (ex: RequireJS).
|
|
||||||
} else if( typeof exports !== 'undefined' ) {
|
|
||||||
module.exports = factory(); // Define as CommonJS module for Node.js, if available.
|
|
||||||
} else {
|
|
||||||
root.Autolinker = factory(); // Finally, define as a browser global if no module loader.
|
|
||||||
}
|
|
||||||
}( this, function() {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Autolinker
|
* @class Autolinker
|
||||||
* @extends Object
|
* @extends Object
|
||||||
|
|
@ -112,6 +116,8 @@
|
||||||
*/
|
*/
|
||||||
var Autolinker = function( cfg ) {
|
var Autolinker = function( cfg ) {
|
||||||
Autolinker.Util.assign( this, cfg ); // assign the properties of `cfg` onto the Autolinker instance. Prototype properties will be used for missing configs.
|
Autolinker.Util.assign( this, cfg ); // assign the properties of `cfg` onto the Autolinker instance. Prototype properties will be used for missing configs.
|
||||||
|
|
||||||
|
this.matchValidator = new Autolinker.MatchValidator();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -204,7 +210,7 @@
|
||||||
*
|
*
|
||||||
* Ignoring & as it could be part of a query string -- handling it separately.
|
* Ignoring & as it could be part of a query string -- handling it separately.
|
||||||
*/
|
*/
|
||||||
htmlCharacterEntitiesRegex: /( | |<|<|>|>)/gi,
|
htmlCharacterEntitiesRegex: /( | |<|<|>|>|"|"|')/gi,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
|
|
@ -224,10 +230,12 @@
|
||||||
* address. Ex: 'me@my.com'
|
* address. Ex: 'me@my.com'
|
||||||
* 5. Group that matches a URL in the input text. Ex: 'http://google.com', 'www.google.com', or just 'google.com'.
|
* 5. Group that matches a URL in the input text. Ex: 'http://google.com', 'www.google.com', or just 'google.com'.
|
||||||
* This also includes a path, url parameters, or hash anchors. Ex: google.com/path/to/file?q1=1&q2=2#myAnchor
|
* This also includes a path, url parameters, or hash anchors. Ex: google.com/path/to/file?q1=1&q2=2#myAnchor
|
||||||
* 6. A protocol-relative ('//') match for the case of a 'www.' prefixed URL. Will be an empty string if it is not a
|
* 6. Group that matches a protocol URL (i.e. 'http://google.com'). This is used to match protocol URLs with just a single
|
||||||
|
* word, like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
|
||||||
|
* 7. A protocol-relative ('//') match for the case of a 'www.' prefixed URL. Will be an empty string if it is not a
|
||||||
* protocol-relative match. We need to know the character before the '//' in order to determine if it is a valid match
|
* protocol-relative match. We need to know the character before the '//' in order to determine if it is a valid match
|
||||||
* or the // was in a string we don't want to auto-link.
|
* or the // was in a string we don't want to auto-link.
|
||||||
* 7. A protocol-relative ('//') match for the case of a known TLD prefixed URL. Will be an empty string if it is not a
|
* 8. A protocol-relative ('//') match for the case of a known TLD prefixed URL. Will be an empty string if it is not a
|
||||||
* protocol-relative match. See #6 for more info.
|
* protocol-relative match. See #6 for more info.
|
||||||
*/
|
*/
|
||||||
matcherRegex : (function() {
|
matcherRegex : (function() {
|
||||||
|
|
@ -235,14 +243,14 @@
|
||||||
|
|
||||||
emailRegex = /(?:[\-;:&=\+\$,\w\.]+@)/, // something@ for email addresses (a.k.a. local-part)
|
emailRegex = /(?:[\-;:&=\+\$,\w\.]+@)/, // something@ for email addresses (a.k.a. local-part)
|
||||||
|
|
||||||
protocolRegex = /(?:[A-Za-z]{3,9}:(?:\/\/)?)/, // match protocol, allow in format http:// or mailto:
|
protocolRegex = /(?:[A-Za-z][-.+A-Za-z0-9]+:(?![A-Za-z][-.+A-Za-z0-9]+:\/\/)(?!\d+\/?)(?:\/\/)?)/, // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex)
|
||||||
wwwRegex = /(?:www\.)/, // starting with 'www.'
|
wwwRegex = /(?:www\.)/, // starting with 'www.'
|
||||||
domainNameRegex = /[A-Za-z0-9\.\-]*[A-Za-z0-9\-]/, // anything looking at all like a domain, non-unicode domains, not ending in a period
|
domainNameRegex = /[A-Za-z0-9\.\-]*[A-Za-z0-9\-]/, // anything looking at all like a domain, non-unicode domains, not ending in a period
|
||||||
tldRegex = /\.(?:international|construction|contractors|enterprises|photography|productions|foundation|immobilien|industries|management|properties|technology|christmas|community|directory|education|equipment|institute|marketing|solutions|vacations|bargains|boutique|builders|catering|cleaning|clothing|computer|democrat|diamonds|graphics|holdings|lighting|partners|plumbing|supplies|training|ventures|academy|careers|company|cruises|domains|exposed|flights|florist|gallery|guitars|holiday|kitchen|neustar|okinawa|recipes|rentals|reviews|shiksha|singles|support|systems|agency|berlin|camera|center|coffee|condos|dating|estate|events|expert|futbol|kaufen|luxury|maison|monash|museum|nagoya|photos|repair|report|social|supply|tattoo|tienda|travel|viajes|villas|vision|voting|voyage|actor|build|cards|cheap|codes|dance|email|glass|house|mango|ninja|parts|photo|shoes|solar|today|tokyo|tools|watch|works|aero|arpa|asia|best|bike|blue|buzz|camp|club|cool|coop|farm|fish|gift|guru|info|jobs|kiwi|kred|land|limo|link|menu|mobi|moda|name|pics|pink|post|qpon|rich|ruhr|sexy|tips|vote|voto|wang|wien|wiki|zone|bar|bid|biz|cab|cat|ceo|com|edu|gov|int|kim|mil|net|onl|org|pro|pub|red|tel|uno|wed|xxx|xyz|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/, // match our known top level domains (TLDs)
|
tldRegex = /\.(?:international|construction|contractors|enterprises|photography|productions|foundation|immobilien|industries|management|properties|technology|christmas|community|directory|education|equipment|institute|marketing|solutions|vacations|bargains|boutique|builders|catering|cleaning|clothing|computer|democrat|diamonds|graphics|holdings|lighting|partners|plumbing|supplies|training|ventures|academy|careers|company|cruises|domains|exposed|flights|florist|gallery|guitars|holiday|kitchen|neustar|okinawa|recipes|rentals|reviews|shiksha|singles|support|systems|agency|berlin|camera|center|coffee|condos|dating|estate|events|expert|futbol|kaufen|luxury|maison|monash|museum|nagoya|photos|repair|report|social|supply|tattoo|tienda|travel|viajes|villas|vision|voting|voyage|actor|build|cards|cheap|codes|dance|email|glass|house|mango|ninja|parts|photo|shoes|solar|today|tokyo|tools|watch|works|aero|arpa|asia|best|bike|blue|buzz|camp|club|cool|coop|farm|fish|gift|guru|info|jobs|kiwi|kred|land|limo|link|menu|mobi|moda|name|pics|pink|post|qpon|rich|ruhr|sexy|tips|vote|voto|wang|wien|wiki|zone|bar|bid|biz|cab|cat|ceo|com|edu|gov|int|kim|mil|net|onl|org|pro|pub|red|tel|uno|wed|xxx|xyz|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/, // match our known top level domains (TLDs)
|
||||||
|
|
||||||
// Allow optional path, query string, and hash anchor, not ending in the following characters: "!:,.;"
|
// Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;"
|
||||||
// http://blog.codinghorror.com/the-problem-with-urls/
|
// http://blog.codinghorror.com/the-problem-with-urls/
|
||||||
urlSuffixRegex = /(?:[\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|])?/; // note: optional part of the full regex
|
urlSuffixRegex = /[\-A-Za-z0-9+&@#\/%=~_()|'$*\[\]?!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|'$*\[\]]/;
|
||||||
|
|
||||||
return new RegExp( [
|
return new RegExp( [
|
||||||
'(', // *** Capturing group $1, which can be used to check for a twitter handle match. Use group $3 for the actual twitter handle though. $2 may be used to reconstruct the original string in a replace()
|
'(', // *** Capturing group $1, which can be used to check for a twitter handle match. Use group $3 for the actual twitter handle though. $2 may be used to reconstruct the original string in a replace()
|
||||||
|
|
@ -263,7 +271,7 @@
|
||||||
|
|
||||||
'(', // *** Capturing group $5, which is used to match a URL
|
'(', // *** Capturing group $5, which is used to match a URL
|
||||||
'(?:', // parens to cover match for protocol (optional), and domain
|
'(?:', // parens to cover match for protocol (optional), and domain
|
||||||
'(?:', // non-capturing paren for a protocol-prefixed url (ex: http://google.com)
|
'(', // *** Capturing group $6, for a protocol-prefixed url (ex: http://google.com)
|
||||||
protocolRegex.source,
|
protocolRegex.source,
|
||||||
domainNameRegex.source,
|
domainNameRegex.source,
|
||||||
')',
|
')',
|
||||||
|
|
@ -271,7 +279,7 @@
|
||||||
'|',
|
'|',
|
||||||
|
|
||||||
'(?:', // non-capturing paren for a 'www.' prefixed url (ex: www.google.com)
|
'(?:', // non-capturing paren for a 'www.' prefixed url (ex: www.google.com)
|
||||||
'(.?//)?', // *** Capturing group $6 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character
|
'(.?//)?', // *** Capturing group $7 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character
|
||||||
wwwRegex.source,
|
wwwRegex.source,
|
||||||
domainNameRegex.source,
|
domainNameRegex.source,
|
||||||
')',
|
')',
|
||||||
|
|
@ -279,33 +287,17 @@
|
||||||
'|',
|
'|',
|
||||||
|
|
||||||
'(?:', // non-capturing paren for known a TLD url (ex: google.com)
|
'(?:', // non-capturing paren for known a TLD url (ex: google.com)
|
||||||
'(.?//)?', // *** Capturing group $7 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character
|
'(.?//)?', // *** Capturing group $8 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character
|
||||||
domainNameRegex.source,
|
domainNameRegex.source,
|
||||||
tldRegex.source,
|
tldRegex.source,
|
||||||
')',
|
')',
|
||||||
')',
|
')',
|
||||||
|
|
||||||
urlSuffixRegex.source, // match for path, query string, and/or hash anchor
|
'(?:' + urlSuffixRegex.source + ')?', // match for path, query string, and/or hash anchor - optional
|
||||||
')'
|
')'
|
||||||
].join( "" ), 'gi' );
|
].join( "" ), 'gi' );
|
||||||
} )(),
|
} )(),
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @property {RegExp} invalidProtocolRelMatchRegex
|
|
||||||
*
|
|
||||||
* The regular expression used to check a potential protocol-relative URL match, coming from the {@link #matcherRegex}.
|
|
||||||
* A protocol-relative URL is, for example, "//yahoo.com"
|
|
||||||
*
|
|
||||||
* This regular expression is used in conjunction with the {@link #matcherRegex}, and checks to see if there is a word character
|
|
||||||
* before the '//' in order to determine if we should actually autolink a protocol-relative URL. This is needed because there
|
|
||||||
* is no negative look-behind in JavaScript regular expressions.
|
|
||||||
*
|
|
||||||
* For instance, we want to autolink something like "//google.com", but we don't want to autolink something
|
|
||||||
* like "abc//google.com"
|
|
||||||
*/
|
|
||||||
invalidProtocolRelMatchRegex : /^[\w]\/\//,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @property {RegExp} charBeforeProtocolRelMatchRegex
|
* @property {RegExp} charBeforeProtocolRelMatchRegex
|
||||||
|
|
@ -318,6 +310,14 @@
|
||||||
*/
|
*/
|
||||||
charBeforeProtocolRelMatchRegex : /^(.)?\/\//,
|
charBeforeProtocolRelMatchRegex : /^(.)?\/\//,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @property {Autolinker.MatchValidator} matchValidator
|
||||||
|
*
|
||||||
|
* The MatchValidator object, used to filter out any false positives from the {@link #matcherRegex}. See
|
||||||
|
* {@link Autolinker.MatchValidator} for details.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @property {Autolinker.HtmlParser} htmlParser
|
* @property {Autolinker.HtmlParser} htmlParser
|
||||||
|
|
@ -345,7 +345,8 @@
|
||||||
* This method finds the text around any HTML elements in the input `textOrHtml`, which will be the text that is processed.
|
* This method finds the text around any HTML elements in the input `textOrHtml`, which will be the text that is processed.
|
||||||
* Any original HTML elements will be left as-is, as well as the text that is already wrapped in anchor (<a>) tags.
|
* Any original HTML elements will be left as-is, as well as the text that is already wrapped in anchor (<a>) tags.
|
||||||
*
|
*
|
||||||
* @param {String} textOrHtml The HTML or text to link URLs, email addresses, and Twitter handles within.
|
* @param {String} textOrHtml The HTML or text to link URLs, email addresses, and Twitter handles within (depending on if
|
||||||
|
* the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled).
|
||||||
* @return {String} The HTML, with URLs/emails/Twitter handles automatically linked.
|
* @return {String} The HTML, with URLs/emails/Twitter handles automatically linked.
|
||||||
*/
|
*/
|
||||||
link : function( textOrHtml ) {
|
link : function( textOrHtml ) {
|
||||||
|
|
@ -455,32 +456,81 @@
|
||||||
* @return {String} The text with anchor tags auto-filled.
|
* @return {String} The text with anchor tags auto-filled.
|
||||||
*/
|
*/
|
||||||
processTextNode : function( text ) {
|
processTextNode : function( text ) {
|
||||||
var me = this, // for closure
|
var me = this; // for closure
|
||||||
charBeforeProtocolRelMatchRegex = this.charBeforeProtocolRelMatchRegex;
|
|
||||||
|
|
||||||
return text.replace( this.matcherRegex, function( matchStr, $1, $2, $3, $4, $5, $6, $7 ) {
|
|
||||||
var twitterMatch = $1,
|
|
||||||
twitterHandlePrefixWhitespaceChar = $2, // The whitespace char before the @ sign in a Twitter handle match. This is needed because of no lookbehinds in JS regexes.
|
|
||||||
twitterHandle = $3, // The actual twitterUser (i.e the word after the @ sign in a Twitter handle match)
|
|
||||||
emailAddressMatch = $4, // For both determining if it is an email address, and stores the actual email address
|
|
||||||
urlMatch = $5, // The matched URL string
|
|
||||||
protocolRelativeMatch = $6 || $7, // The '//' for a protocol-relative match, with the character that comes before the '//'
|
|
||||||
|
|
||||||
prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match
|
|
||||||
suffixStr = "", // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked.
|
|
||||||
|
|
||||||
match; // Will be an Autolinker.match.Match object
|
|
||||||
|
|
||||||
|
return text.replace( this.matcherRegex, function( matchStr, $1, $2, $3, $4, $5, $6, $7, $8 ) {
|
||||||
|
var matchDescObj = me.processCandidateMatch( matchStr, $1, $2, $3, $4, $5, $6, $7, $8 ); // match description object
|
||||||
|
|
||||||
// Return out with no changes for match types that are disabled (url, email, twitter), or for matches that are
|
// Return out with no changes for match types that are disabled (url, email, twitter), or for matches that are
|
||||||
// invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
|
// invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
|
||||||
if( !me.isValidMatch( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) ) {
|
if( !matchDescObj ) {
|
||||||
return matchStr;
|
return matchStr;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Generate the replacement text for the match
|
||||||
|
var matchReturnVal = me.createMatchReturnVal( matchDescObj.match, matchDescObj.matchStr );
|
||||||
|
return matchDescObj.prefixStr + matchReturnVal + matchDescObj.suffixStr;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a candidate match from the {@link #matcherRegex}.
|
||||||
|
*
|
||||||
|
* Not all matches found by the regex are actual URL/email/Twitter matches, as determined by the {@link #matchValidator}. In
|
||||||
|
* this case, the method returns `null`. Otherwise, a valid Object with `prefixStr`, `match`, and `suffixStr` is returned.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} matchStr The full match that was found by the {@link #matcherRegex}.
|
||||||
|
* @param {String} twitterMatch The matched text of a Twitter handle, if the match is a Twitter match.
|
||||||
|
* @param {String} twitterHandlePrefixWhitespaceChar The whitespace char before the @ sign in a Twitter handle match. This
|
||||||
|
* is needed because of no lookbehinds in JS regexes, and is need to re-include the character for the anchor tag replacement.
|
||||||
|
* @param {String} twitterHandle The actual Twitter user (i.e the word after the @ sign in a Twitter match).
|
||||||
|
* @param {String} emailAddressMatch The matched email address for an email address match.
|
||||||
|
* @param {String} urlMatch The matched URL string for a URL match.
|
||||||
|
* @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to match
|
||||||
|
* something like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
|
||||||
|
* @param {String} wwwProtocolRelativeMatch The '//' for a protocol-relative match from a 'www' url, with the character that
|
||||||
|
* comes before the '//'.
|
||||||
|
* @param {String} tldProtocolRelativeMatch The '//' for a protocol-relative match from a TLD (top level domain) match, with
|
||||||
|
* the character that comes before the '//'.
|
||||||
|
*
|
||||||
|
* @return {Object} A "match description object". This will be `null` if the match was invalid, or if a match type is disabled.
|
||||||
|
* Otherwise, this will be an Object (map) with the following properties:
|
||||||
|
* @return {String} return.prefixStr The char(s) that should be prepended to the replacement string. These are char(s) that
|
||||||
|
* were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into
|
||||||
|
* the replacement stream.
|
||||||
|
* @return {String} return.suffixStr The char(s) that should be appended to the replacement string. These are char(s) that
|
||||||
|
* were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into
|
||||||
|
* the replacement stream.
|
||||||
|
* @return {String} return.matchStr The `matchStr`, fixed up to remove characters that are no longer needed (which have been
|
||||||
|
* added to `prefixStr` and `suffixStr`).
|
||||||
|
* @return {Autolinker.match.Match} return.match The Match object that represents the match that was found.
|
||||||
|
*/
|
||||||
|
processCandidateMatch : function(
|
||||||
|
matchStr, twitterMatch, twitterHandlePrefixWhitespaceChar, twitterHandle,
|
||||||
|
emailAddressMatch, urlMatch, protocolUrlMatch, wwwProtocolRelativeMatch, tldProtocolRelativeMatch
|
||||||
|
) {
|
||||||
|
var protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch,
|
||||||
|
match, // Will be an Autolinker.match.Match object
|
||||||
|
|
||||||
|
prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match
|
||||||
|
suffixStr = ""; // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked.
|
||||||
|
|
||||||
|
|
||||||
|
// Return out with `null` for match types that are disabled (url, email, twitter), or for matches that are
|
||||||
|
// invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
|
||||||
|
if(
|
||||||
|
( twitterMatch && !this.twitter ) || ( emailAddressMatch && !this.email ) || ( urlMatch && !this.urls ) ||
|
||||||
|
!this.matchValidator.isValidMatch( urlMatch, protocolUrlMatch, protocolRelativeMatch )
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle a closing parenthesis at the end of the match, and exclude it if there is not a matching open parenthesis
|
// Handle a closing parenthesis at the end of the match, and exclude it if there is not a matching open parenthesis
|
||||||
// in the match itself.
|
// in the match itself.
|
||||||
if( me.matchHasUnbalancedClosingParen( matchStr ) ) {
|
if( this.matchHasUnbalancedClosingParen( matchStr ) ) {
|
||||||
matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")"
|
matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")"
|
||||||
suffixStr = ")"; // this will be added after the generated <a> tag
|
suffixStr = ")"; // this will be added after the generated <a> tag
|
||||||
}
|
}
|
||||||
|
|
@ -502,7 +552,7 @@
|
||||||
// If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed
|
// If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed
|
||||||
// to match due to the lack of a negative look-behind in JavaScript regular expressions)
|
// to match due to the lack of a negative look-behind in JavaScript regular expressions)
|
||||||
if( protocolRelativeMatch ) {
|
if( protocolRelativeMatch ) {
|
||||||
var charBeforeMatch = protocolRelativeMatch.match( charBeforeProtocolRelMatchRegex )[ 1 ] || "";
|
var charBeforeMatch = protocolRelativeMatch.match( this.charBeforeProtocolRelMatchRegex )[ 1 ] || "";
|
||||||
|
|
||||||
if( charBeforeMatch ) { // fix up the `matchStr` if there was a preceding char before a protocol-relative match, which was needed to determine the match itself (since there are no look-behinds in JS regexes)
|
if( charBeforeMatch ) { // fix up the `matchStr` if there was a preceding char before a protocol-relative match, which was needed to determine the match itself (since there are no look-behinds in JS regexes)
|
||||||
prefixStr = charBeforeMatch;
|
prefixStr = charBeforeMatch;
|
||||||
|
|
@ -513,52 +563,18 @@
|
||||||
match = new Autolinker.match.Url( {
|
match = new Autolinker.match.Url( {
|
||||||
matchedText : matchStr,
|
matchedText : matchStr,
|
||||||
url : matchStr,
|
url : matchStr,
|
||||||
protocolRelativeMatch : protocolRelativeMatch,
|
protocolUrlMatch : !!protocolUrlMatch,
|
||||||
stripPrefix : me.stripPrefix
|
protocolRelativeMatch : !!protocolRelativeMatch,
|
||||||
|
stripPrefix : this.stripPrefix
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the replacement text for the match
|
return {
|
||||||
var matchReturnVal = me.createMatchReturnVal( match, matchStr );
|
prefixStr : prefixStr,
|
||||||
return prefixStr + matchReturnVal + suffixStr;
|
suffixStr : suffixStr,
|
||||||
} );
|
matchStr : matchStr,
|
||||||
},
|
match : match
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if a given match found by {@link #processTextNode} is valid. Will return `false` for:
|
|
||||||
*
|
|
||||||
* 1) Disabled link types (i.e. having a Twitter match, but {@link #twitter} matching is disabled)
|
|
||||||
* 2) URL matches which do not have at least have one period ('.') in the domain name (effectively skipping over
|
|
||||||
* matches like "abc:def")
|
|
||||||
* 3) A protocol-relative url match (a URL beginning with '//') whose previous character is a word character
|
|
||||||
* (effectively skipping over strings like "abc//google.com")
|
|
||||||
*
|
|
||||||
* Otherwise, returns `true`.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {String} twitterMatch The matched Twitter handle, if there was one. Will be empty string if the match is not a
|
|
||||||
* Twitter match.
|
|
||||||
* @param {String} emailAddressMatch The matched Email address, if there was one. Will be empty string if the match is not
|
|
||||||
* an Email address match.
|
|
||||||
* @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
|
|
||||||
* @param {String} protocolRelativeMatch The protocol-relative string for a URL match (i.e. '//'), possibly with a preceding
|
|
||||||
* character (ex, a space, such as: ' //', or a letter, such as: 'a//'). The match is invalid if there is a word character
|
|
||||||
* preceding the '//'.
|
|
||||||
* @return {Boolean} `true` if the match given is valid and should be processed, or `false` if the match is invalid and/or
|
|
||||||
* should just not be processed (such as, if it's a Twitter match, but {@link #twitter} matching is disabled}.
|
|
||||||
*/
|
|
||||||
isValidMatch : function( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) {
|
|
||||||
if(
|
|
||||||
( twitterMatch && !this.twitter ) || ( emailAddressMatch && !this.email ) || ( urlMatch && !this.urls ) ||
|
|
||||||
( urlMatch && urlMatch.indexOf( '.' ) === -1 ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL
|
|
||||||
( urlMatch && /^[A-Za-z]{3,9}:/.test( urlMatch ) && !/:.*?[A-Za-z]/.test( urlMatch ) ) || // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0"
|
|
||||||
( protocolRelativeMatch && this.invalidProtocolRelMatchRegex.test( protocolRelativeMatch ) ) // a protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com")
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -648,15 +664,15 @@
|
||||||
* // Produces: "Go to <a href="http://google.com">google.com</a>"
|
* // Produces: "Go to <a href="http://google.com">google.com</a>"
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @method link
|
* @param {String} textOrHtml The HTML or text to find URLs, email addresses, and Twitter handles within (depending on if
|
||||||
* @param {String} html The HTML text to link URLs within.
|
* the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled).
|
||||||
* @param {Object} [options] Any of the configuration options for the Autolinker class, specified in an Object (map).
|
* @param {Object} [options] Any of the configuration options for the Autolinker class, specified in an Object (map).
|
||||||
* See the class description for an example call.
|
* See the class description for an example call.
|
||||||
* @return {String} The HTML text, with URLs automatically linked
|
* @return {String} The HTML text, with URLs automatically linked
|
||||||
*/
|
*/
|
||||||
Autolinker.link = function( text, options ) {
|
Autolinker.link = function( textOrHtml, options ) {
|
||||||
var autolinker = new Autolinker( options );
|
var autolinker = new Autolinker( options );
|
||||||
return autolinker.link( text );
|
return autolinker.link( textOrHtml );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -685,7 +701,7 @@
|
||||||
*
|
*
|
||||||
* @param {Object} dest The destination object.
|
* @param {Object} dest The destination object.
|
||||||
* @param {Object} src The source object.
|
* @param {Object} src The source object.
|
||||||
* @return {Object} The destination object.
|
* @return {Object} The destination object (`dest`)
|
||||||
*/
|
*/
|
||||||
assign : function( dest, src ) {
|
assign : function( dest, src ) {
|
||||||
for( var prop in src ) {
|
for( var prop in src ) {
|
||||||
|
|
@ -834,34 +850,53 @@
|
||||||
*
|
*
|
||||||
* Capturing groups:
|
* Capturing groups:
|
||||||
*
|
*
|
||||||
* 1. If it is an end tag, this group will have the '/'.
|
* 1. The "!DOCTYPE" tag name, if a tag is a <!DOCTYPE> tag.
|
||||||
* 2. The tag name.
|
* 2. If it is an end tag, this group will have the '/'.
|
||||||
|
* 3. The tag name for all tags (other than the <!DOCTYPE> tag)
|
||||||
*/
|
*/
|
||||||
htmlRegex : (function() {
|
htmlRegex : (function() {
|
||||||
var tagNameRegex = /[0-9a-zA-Z:]+/,
|
var tagNameRegex = /[0-9a-zA-Z][0-9a-zA-Z:]*/,
|
||||||
attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char
|
attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char
|
||||||
attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values
|
attrValueRegex = /(?:"[^"]*?"|'[^']*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values
|
||||||
nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?'; // optional '=[value]'
|
nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?'; // optional '=[value]'
|
||||||
|
|
||||||
return new RegExp( [
|
return new RegExp( [
|
||||||
'<(?:!|(/))?', // Beginning of a tag. Either '<' for a start tag, '</' for an end tag, or <! for the <!DOCTYPE ...> tag. The slash or an empty string is Capturing Group 1.
|
// for <!DOCTYPE> tag. Ex: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
|
||||||
|
'(?:',
|
||||||
// The tag name (Capturing Group 2)
|
'<(!DOCTYPE)', // *** Capturing Group 1 - If it's a doctype tag
|
||||||
'(' + tagNameRegex.source + ')',
|
|
||||||
|
|
||||||
// Zero or more attributes following the tag name
|
// Zero or more attributes following the tag name
|
||||||
'(?:',
|
'(?:',
|
||||||
'\\s+', // one or more whitespace chars before an attribute
|
'\\s+', // one or more whitespace chars before an attribute
|
||||||
|
|
||||||
// Either:
|
// Either:
|
||||||
// A. tag="value", or
|
// A. attr="value", or
|
||||||
// B. "value" alone (for <!DOCTYPE> tag. Ex: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
|
// B. "value" alone (To cover example doctype tag: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
|
||||||
'(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')',
|
'(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')',
|
||||||
')*',
|
')*',
|
||||||
|
'>',
|
||||||
|
')',
|
||||||
|
|
||||||
|
'|',
|
||||||
|
|
||||||
|
// All other HTML tags (i.e. tags that are not <!DOCTYPE>)
|
||||||
|
'(?:',
|
||||||
|
'<(/)?', // Beginning of a tag. Either '<' for a start tag, or '</' for an end tag.
|
||||||
|
// *** Capturing Group 2: The slash or an empty string. Slash ('/') for end tag, empty string for start or self-closing tag.
|
||||||
|
|
||||||
|
// *** Capturing Group 3 - The tag name
|
||||||
|
'(' + tagNameRegex.source + ')',
|
||||||
|
|
||||||
|
// Zero or more attributes following the tag name
|
||||||
|
'(?:',
|
||||||
|
'\\s+', // one or more whitespace chars before an attribute
|
||||||
|
nameEqualsValueRegex, // attr="value" (with optional ="value" part)
|
||||||
|
')*',
|
||||||
|
|
||||||
'\\s*/?', // any trailing spaces and optional '/' before the closing '>'
|
'\\s*/?', // any trailing spaces and optional '/' before the closing '>'
|
||||||
'>'
|
'>',
|
||||||
].join( "" ), 'g' );
|
')'
|
||||||
|
].join( "" ), 'gi' );
|
||||||
} )(),
|
} )(),
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -895,15 +930,15 @@
|
||||||
// wrapping the URLs in anchor tags
|
// wrapping the URLs in anchor tags
|
||||||
while( ( currentResult = htmlRegex.exec( html ) ) !== null ) {
|
while( ( currentResult = htmlRegex.exec( html ) ) !== null ) {
|
||||||
var tagText = currentResult[ 0 ],
|
var tagText = currentResult[ 0 ],
|
||||||
tagName = currentResult[ 2 ],
|
tagName = currentResult[ 1 ] || currentResult[ 3 ], // The <!DOCTYPE> tag (ex: "!DOCTYPE"), or another tag (ex: "a")
|
||||||
isClosingTag = !!currentResult[ 1 ],
|
isClosingTag = !!currentResult[ 2 ],
|
||||||
inBetweenTagsText = html.substring( lastIndex, currentResult.index );
|
inBetweenTagsText = html.substring( lastIndex, currentResult.index );
|
||||||
|
|
||||||
if( inBetweenTagsText ) {
|
if( inBetweenTagsText ) {
|
||||||
processTextNodeVisitor( inBetweenTagsText );
|
processTextNodeVisitor( inBetweenTagsText );
|
||||||
}
|
}
|
||||||
|
|
||||||
processHtmlNodeVisitor( tagText, tagName, isClosingTag );
|
processHtmlNodeVisitor( tagText, tagName.toLowerCase(), isClosingTag );
|
||||||
|
|
||||||
lastIndex = currentResult.index + tagText.length;
|
lastIndex = currentResult.index + tagText.length;
|
||||||
}
|
}
|
||||||
|
|
@ -1266,6 +1301,175 @@
|
||||||
return attrsArr.join( " " );
|
return attrsArr.join( " " );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
/*global Autolinker */
|
||||||
|
/*jshint scripturl:true */
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @class Autolinker.MatchValidator
|
||||||
|
* @extends Object
|
||||||
|
*
|
||||||
|
* Used by Autolinker to filter out false positives from the {@link Autolinker#matcherRegex}.
|
||||||
|
*
|
||||||
|
* Due to the limitations of regular expressions (including the missing feature of look-behinds in JS regular expressions),
|
||||||
|
* we cannot always determine the validity of a given match. This class applies a bit of additional logic to filter out any
|
||||||
|
* false positives that have been matched by the {@link Autolinker#matcherRegex}.
|
||||||
|
*/
|
||||||
|
Autolinker.MatchValidator = Autolinker.Util.extend( Object, {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @property {RegExp} invalidProtocolRelMatchRegex
|
||||||
|
*
|
||||||
|
* The regular expression used to check a potential protocol-relative URL match, coming from the
|
||||||
|
* {@link Autolinker#matcherRegex}. A protocol-relative URL is, for example, "//yahoo.com"
|
||||||
|
*
|
||||||
|
* This regular expression checks to see if there is a word character before the '//' match in order to determine if
|
||||||
|
* we should actually autolink a protocol-relative URL. This is needed because there is no negative look-behind in
|
||||||
|
* JavaScript regular expressions.
|
||||||
|
*
|
||||||
|
* For instance, we want to autolink something like "Go to: //google.com", but we don't want to autolink something
|
||||||
|
* like "abc//google.com"
|
||||||
|
*/
|
||||||
|
invalidProtocolRelMatchRegex : /^[\w]\/\//,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://'
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @property {RegExp} hasFullProtocolRegex
|
||||||
|
*/
|
||||||
|
hasFullProtocolRegex : /^[A-Za-z][-.+A-Za-z0-9]+:\/\//,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex to find the URI scheme, such as 'mailto:'.
|
||||||
|
*
|
||||||
|
* This is used to filter out 'javascript:' and 'vbscript:' schemes.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @property {RegExp} uriSchemeRegex
|
||||||
|
*/
|
||||||
|
uriSchemeRegex : /^[A-Za-z][-.+A-Za-z0-9]+:/,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex to determine if at least one word char exists after the protocol (i.e. after the ':')
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @property {RegExp} hasWordCharAfterProtocolRegex
|
||||||
|
*/
|
||||||
|
hasWordCharAfterProtocolRegex : /:[^\s]*?[A-Za-z]/,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a given match found by {@link Autolinker#processTextNode} is valid. Will return `false` for:
|
||||||
|
*
|
||||||
|
* 1) URL matches which do not have at least have one period ('.') in the domain name (effectively skipping over
|
||||||
|
* matches like "abc:def"). However, URL matches with a protocol will be allowed (ex: 'http://localhost')
|
||||||
|
* 2) URL matches which do not have at least one word character in the domain name (effectively skipping over
|
||||||
|
* matches like "git:1.0").
|
||||||
|
* 3) A protocol-relative url match (a URL beginning with '//') whose previous character is a word character
|
||||||
|
* (effectively skipping over strings like "abc//google.com")
|
||||||
|
*
|
||||||
|
* Otherwise, returns `true`.
|
||||||
|
*
|
||||||
|
* @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
|
||||||
|
* @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to match
|
||||||
|
* something like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
|
||||||
|
* @param {String} protocolRelativeMatch The protocol-relative string for a URL match (i.e. '//'), possibly with a preceding
|
||||||
|
* character (ex, a space, such as: ' //', or a letter, such as: 'a//'). The match is invalid if there is a word character
|
||||||
|
* preceding the '//'.
|
||||||
|
* @return {Boolean} `true` if the match given is valid and should be processed, or `false` if the match is invalid and/or
|
||||||
|
* should just not be processed.
|
||||||
|
*/
|
||||||
|
isValidMatch : function( urlMatch, protocolUrlMatch, protocolRelativeMatch ) {
|
||||||
|
if(
|
||||||
|
( protocolUrlMatch && !this.isValidUriScheme( protocolUrlMatch ) ) ||
|
||||||
|
this.urlMatchDoesNotHaveProtocolOrDot( urlMatch, protocolUrlMatch ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost')
|
||||||
|
this.urlMatchDoesNotHaveAtLeastOneWordChar( urlMatch, protocolUrlMatch ) || // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0"
|
||||||
|
this.isInvalidProtocolRelativeMatch( protocolRelativeMatch ) // A protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com")
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the URI scheme is a valid scheme to be autolinked. Returns `false` if the scheme is
|
||||||
|
* 'javascript:' or 'vbscript:'
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} uriSchemeMatch The match URL string for a full URI scheme match. Ex: 'http://yahoo.com'
|
||||||
|
* or 'mailto:a@a.com'.
|
||||||
|
* @return {Boolean} `true` if the scheme is a valid one, `false` otherwise.
|
||||||
|
*/
|
||||||
|
isValidUriScheme : function( uriSchemeMatch ) {
|
||||||
|
var uriScheme = uriSchemeMatch.match( this.uriSchemeRegex )[ 0 ];
|
||||||
|
|
||||||
|
return ( uriScheme !== 'javascript:' && uriScheme !== 'vbscript:' );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a URL match does not have either:
|
||||||
|
*
|
||||||
|
* a) a full protocol (i.e. 'http://'), or
|
||||||
|
* b) at least one dot ('.') in the domain name (for a non-full-protocol match).
|
||||||
|
*
|
||||||
|
* Either situation is considered an invalid URL (ex: 'git:d' does not have either the '://' part, or at least one dot
|
||||||
|
* in the domain name. If the match was 'git:abc.com', we would consider this valid.)
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
|
||||||
|
* @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to match
|
||||||
|
* something like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
|
||||||
|
* @return {Boolean} `true` if the URL match does not have a full protocol, or at least one dot ('.') in a non-full-protocol
|
||||||
|
* match.
|
||||||
|
*/
|
||||||
|
urlMatchDoesNotHaveProtocolOrDot : function( urlMatch, protocolUrlMatch ) {
|
||||||
|
return ( !!urlMatch && ( !protocolUrlMatch || !this.hasFullProtocolRegex.test( protocolUrlMatch ) ) && urlMatch.indexOf( '.' ) === -1 );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a URL match does not have at least one word character after the protocol (i.e. in the domain name).
|
||||||
|
*
|
||||||
|
* At least one letter character must exist in the domain name after a protocol match. Ex: skip over something
|
||||||
|
* like "git:1.0"
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
|
||||||
|
* @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to
|
||||||
|
* know whether or not we have a protocol in the URL string, in order to check for a word character after the protocol
|
||||||
|
* separator (':').
|
||||||
|
* @return {Boolean} `true` if the URL match does not have at least one word character in it after the protocol, `false`
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
urlMatchDoesNotHaveAtLeastOneWordChar : function( urlMatch, protocolUrlMatch ) {
|
||||||
|
if( urlMatch && protocolUrlMatch ) {
|
||||||
|
return !this.hasWordCharAfterProtocolRegex.test( urlMatch );
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a protocol-relative match is an invalid one. This method returns `true` if there is a `protocolRelativeMatch`,
|
||||||
|
* and that match contains a word character before the '//' (i.e. it must contain whitespace or nothing before the '//' in
|
||||||
|
* order to be considered valid).
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} protocolRelativeMatch The protocol-relative string for a URL match (i.e. '//'), possibly with a preceding
|
||||||
|
* character (ex, a space, such as: ' //', or a letter, such as: 'a//'). The match is invalid if there is a word character
|
||||||
|
* preceding the '//'.
|
||||||
|
* @return {Boolean} `true` if it is an invalid protocol-relative match, `false` otherwise.
|
||||||
|
*/
|
||||||
|
isInvalidProtocolRelativeMatch : function( protocolRelativeMatch ) {
|
||||||
|
return ( !!protocolRelativeMatch && this.invalidProtocolRelMatchRegex.test( protocolRelativeMatch ) );
|
||||||
|
}
|
||||||
|
|
||||||
} );
|
} );
|
||||||
/*global Autolinker */
|
/*global Autolinker */
|
||||||
/*jshint sub:true */
|
/*jshint sub:true */
|
||||||
|
|
@ -1628,6 +1832,13 @@
|
||||||
* The url that was matched.
|
* The url that was matched.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @cfg {Boolean} protocolUrlMatch (required)
|
||||||
|
*
|
||||||
|
* `true` if the URL is a match which already has a protocol (i.e. 'http://'), `false` if the match was from a 'www' or
|
||||||
|
* known TLD match.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @cfg {Boolean} protocolRelativeMatch (required)
|
* @cfg {Boolean} protocolRelativeMatch (required)
|
||||||
*
|
*
|
||||||
|
|
@ -1637,7 +1848,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @cfg {Boolean} stripPrefix (required)
|
* @cfg {Boolean} stripPrefix (required)
|
||||||
* @inheritdoc {@link Autolinker#stripPrefix}
|
* @inheritdoc Autolinker#stripPrefix
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1659,13 +1870,13 @@
|
||||||
protocolRelativeRegex : /^\/\//,
|
protocolRelativeRegex : /^\/\//,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @private
|
||||||
* @property {RegExp} checkForProtocolRegex
|
* @property {Boolean} protocolPrepended
|
||||||
*
|
*
|
||||||
* A regular expression used to check if the {@link #url} is missing a protocol (in which case, 'http://'
|
* Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the
|
||||||
* will be added).
|
* {@link #url} did not have a protocol)
|
||||||
*/
|
*/
|
||||||
checkForProtocolRegex: /^[A-Za-z]{3,9}:/,
|
protocolPrepended : false,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1679,17 +1890,19 @@
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the url that was matched, assuming the protocol to be 'http://' if the match
|
* Returns the url that was matched, assuming the protocol to be 'http://' if the original
|
||||||
* was missing a protocol.
|
* match was missing a protocol.
|
||||||
*
|
*
|
||||||
* @return {String}
|
* @return {String}
|
||||||
*/
|
*/
|
||||||
getUrl : function() {
|
getUrl : function() {
|
||||||
var url = this.url;
|
var url = this.url;
|
||||||
|
|
||||||
// if the url string doesn't begin with a protocol, assume http://
|
// if the url string doesn't begin with a protocol, assume 'http://'
|
||||||
if( !this.protocolRelativeMatch && !this.checkForProtocolRegex.test( url ) ) {
|
if( !this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended ) {
|
||||||
url = this.url = 'http://' + url;
|
url = this.url = 'http://' + url;
|
||||||
|
|
||||||
|
this.protocolPrepended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
|
|
@ -1778,4 +1991,5 @@
|
||||||
|
|
||||||
return Autolinker;
|
return Autolinker;
|
||||||
|
|
||||||
|
|
||||||
}));
|
}));
|
||||||
6
vendors/Autolinker/Autolinker.min.js
vendored
6
vendors/Autolinker/Autolinker.min.js
vendored
File diff suppressed because one or more lines are too long
164
vendors/Autolinker/README.md
vendored
164
vendors/Autolinker/README.md
vendored
|
|
@ -50,13 +50,13 @@ JavaScript:
|
||||||
```javascript
|
```javascript
|
||||||
var Autolinker = require( 'autolinker' );
|
var Autolinker = require( 'autolinker' );
|
||||||
// note: npm wants an all-lowercase package name, but the utility is a class and should be
|
// note: npm wants an all-lowercase package name, but the utility is a class and should be
|
||||||
// aliased with a captial letter
|
// aliased with a capital letter
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Using the static `link()` method:
|
Using the static [link()](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-static-method-link) method:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var linkedText = Autolinker.link( textToAutolink[, options] );
|
var linkedText = Autolinker.link( textToAutolink[, options] );
|
||||||
|
|
@ -71,7 +71,7 @@ var linkedText = autolinker.link( textToAutoLink );
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: if using the same options to autolink multiple pieces of html/text, it is slightly more efficient to create a single
|
Note: if using the same options to autolink multiple pieces of html/text, it is slightly more efficient to create a single
|
||||||
Autolinker instance, and run the `link()` method repeatedly (i.e. use the "class" form above).
|
Autolinker instance, and run the [link()](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-method-link) method repeatedly (i.e. use the "class" form above).
|
||||||
|
|
||||||
|
|
||||||
#### Example:
|
#### Example:
|
||||||
|
|
@ -83,16 +83,16 @@ var linkedText = Autolinker.link( "Check out google.com", { className: "myLink"
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
These are the options which may be specified for linking. These are specified by providing an Object as the second parameter to `Autolinker.link()`. These include:
|
These are the options which may be specified for linking. These are specified by providing an Object as the second parameter to [Autolinker.link()](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-static-method-link). These include:
|
||||||
|
|
||||||
- **newWindow** : Boolean<br />
|
- [newWindow](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-newWindow) : Boolean<br />
|
||||||
`true` to have the links should open in a new window when clicked, `false` otherwise. Defaults to `true`.<br /><br />
|
`true` to have the links should open in a new window when clicked, `false` otherwise. Defaults to `true`.<br /><br />
|
||||||
- **stripPrefix** : Boolean<br />
|
- [stripPrefix](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-stripPrefix) : Boolean<br />
|
||||||
`true` to have the 'http://' or 'https://' and/or the 'www.' stripped from the beginning of links, `false` otherwise. Defaults to `true`.<br /><br />
|
`true` to have the 'http://' or 'https://' and/or the 'www.' stripped from the beginning of links, `false` otherwise. Defaults to `true`.<br /><br />
|
||||||
- **truncate** : Number<br />
|
- [truncate](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-truncate) : Number<br />
|
||||||
A number for how many characters long URLs/emails/twitter handles should be truncated to inside the text of a link. If the URL/email/twitter is over the number of characters, it will be truncated to this length by replacing the end of the string with a two period ellipsis ('..').<br /><br />
|
A number for how many characters long URLs/emails/twitter handles should be truncated to inside the text of a link. If the URL/email/twitter is over the number of characters, it will be truncated to this length by replacing the end of the string with a two period ellipsis ('..').<br /><br />
|
||||||
Example: a url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters may look like this: 'yahoo.com/some/long/pat..'<br />
|
Example: a url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters may look like this: 'yahoo.com/some/long/pat..'<br /><br />
|
||||||
- **className** : String<br />
|
- [className](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-className) : String<br />
|
||||||
A CSS class name to add to the generated anchor tags. This class will be added to all links, as well as this class
|
A CSS class name to add to the generated anchor tags. This class will be added to all links, as well as this class
|
||||||
plus "url"/"email"/"twitter" suffixes for styling url/email/twitter links differently.
|
plus "url"/"email"/"twitter" suffixes for styling url/email/twitter links differently.
|
||||||
|
|
||||||
|
|
@ -102,18 +102,18 @@ These are the options which may be specified for linking. These are specified by
|
||||||
2) Email links will have the CSS classes: "myLink myLink-email", and<br />
|
2) Email links will have the CSS classes: "myLink myLink-email", and<br />
|
||||||
3) Twitter links will have the CSS classes: "myLink myLink-twitter"<br />
|
3) Twitter links will have the CSS classes: "myLink myLink-twitter"<br />
|
||||||
|
|
||||||
- **urls** : Boolean<br />
|
- [urls](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-urls) : Boolean<br />
|
||||||
`true` to have URLs auto-linked, `false` to skip auto-linking of URLs. Defaults to `true`.<br />
|
`true` to have URLs auto-linked, `false` to skip auto-linking of URLs. Defaults to `true`.<br />
|
||||||
- **email** : Boolean<br />
|
- [email](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-email) : Boolean<br />
|
||||||
`true` to have email addresses auto-linked, `false` to skip auto-linking of email addresses. Defaults to `true`.<br /><br />
|
`true` to have email addresses auto-linked, `false` to skip auto-linking of email addresses. Defaults to `true`.<br /><br />
|
||||||
- **twitter** : Boolean<br />
|
- [twitter](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-twitter) : Boolean<br />
|
||||||
`true` to have Twitter handles auto-linked, `false` to skip auto-linking of Twitter handles. Defaults to `true`.
|
`true` to have Twitter handles auto-linked, `false` to skip auto-linking of Twitter handles. Defaults to `true`.<br /><br />
|
||||||
- **replaceFn** : Function<br />
|
- [replaceFn](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-replaceFn) : Function<br />
|
||||||
A function to use to programmatically make replacements of matches in the input string, one at a time. See the section
|
A function to use to programmatically make replacements of matches in the input string, one at a time. See the section
|
||||||
<a href="#custom-replacement-function">Custom Replacement Function</a> for more details.
|
<a href="#custom-replacement-function">Custom Replacement Function</a> for more details.
|
||||||
|
|
||||||
|
|
||||||
For example, if you wanted to disable links from opening in new windows, you could do:
|
For example, if you wanted to disable links from opening in [new windows](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-newWindow), you could do:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var linkedText = Autolinker.link( "Check out google.com", { newWindow: false } );
|
var linkedText = Autolinker.link( "Check out google.com", { newWindow: false } );
|
||||||
|
|
@ -135,7 +135,7 @@ var myTextEl = document.getElementById( 'text' );
|
||||||
myTextEl.innerHTML = Autolinker.link( myTextEl.innerHTML );
|
myTextEl.innerHTML = Autolinker.link( myTextEl.innerHTML );
|
||||||
```
|
```
|
||||||
|
|
||||||
Using the same pre-configured Autolinker instance in multiple locations of a codebase (usually by dependency injection):
|
Using the same pre-configured [Autolinker](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker) instance in multiple locations of a codebase (usually by dependency injection):
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var autolinker = new Autolinker( { newWindow: false, truncate: 25 } );
|
var autolinker = new Autolinker( { newWindow: false, truncate: 25 } );
|
||||||
|
|
@ -155,7 +155,7 @@ autolinker.link( "Go to www.google.com" );
|
||||||
|
|
||||||
## Custom Replacement Function
|
## Custom Replacement Function
|
||||||
|
|
||||||
A custom replacement function (`replaceFn`) may be provided to replace url/email/twitter matches on an individual basis, based
|
A custom replacement function ([replaceFn](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-replaceFn)) may be provided to replace url/email/twitter matches on an individual basis, based
|
||||||
on the return from this function.
|
on the return from this function.
|
||||||
|
|
||||||
Full example, for purposes of documenting the API:
|
Full example, for purposes of documenting the API:
|
||||||
|
|
@ -207,8 +207,8 @@ var linkedText = Autolinker.link( input, {
|
||||||
The function is provided two arguments:
|
The function is provided two arguments:
|
||||||
|
|
||||||
1. The Autolinker instance that is performing replacements. This can be used to query the options that the Autolinker
|
1. The Autolinker instance that is performing replacements. This can be used to query the options that the Autolinker
|
||||||
instance is configured with, or to retrieve its TagBuilder instance (via `autolinker.getTagBuilder()`).
|
instance is configured with, or to retrieve its TagBuilder instance (via [autolinker.getTagBuilder()](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-method-getTagBuilder)).
|
||||||
2. An `Autolinker.match.Match` object which details the match that is to be replaced.
|
2. An [Autolinker.match.Match](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker.match.Match) object which details the match that is to be replaced.
|
||||||
|
|
||||||
|
|
||||||
A replacement of the match is made based on the return value of the function. The following return values may be provided:
|
A replacement of the match is made based on the return value of the function. The following return values may be provided:
|
||||||
|
|
@ -217,7 +217,7 @@ A replacement of the match is made based on the return value of the function. Th
|
||||||
- `false` (Boolean): Do not replace the current match at all - leave as-is.
|
- `false` (Boolean): Do not replace the current match at all - leave as-is.
|
||||||
- Any String: If a string is returned from the function, the string will be used directly as the replacement HTML for
|
- Any String: If a string is returned from the function, the string will be used directly as the replacement HTML for
|
||||||
the match.
|
the match.
|
||||||
- An `Autolinker.HtmlTag` instance, which can be used to build/modify an HTML tag before writing out its HTML text.
|
- An [Autolinker.HtmlTag](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker.HtmlTag) instance, which can be used to build/modify an HTML tag before writing out its HTML text.
|
||||||
|
|
||||||
|
|
||||||
## Full API Docs
|
## Full API Docs
|
||||||
|
|
@ -225,126 +225,6 @@ A replacement of the match is made based on the return value of the function. Th
|
||||||
The full API docs for Autolinker may be referenced at: [http://gregjacobs.github.io/Autolinker.js/docs/](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker)
|
The full API docs for Autolinker may be referenced at: [http://gregjacobs.github.io/Autolinker.js/docs/](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker)
|
||||||
|
|
||||||
|
|
||||||
## Changelog:
|
## Changelog
|
||||||
|
|
||||||
### 0.12.3
|
See [Releases](https://github.com/gregjacobs/Autolinker.js/releases)
|
||||||
|
|
||||||
- Add `Autolinker.match.Match#getMatchedText` method
|
|
||||||
|
|
||||||
### 0.12.2
|
|
||||||
|
|
||||||
- Add documentation generation, and update inline documentation.
|
|
||||||
|
|
||||||
### 0.12.1
|
|
||||||
|
|
||||||
- Expose the `Autolinker.HtmlTag` class, and allow it to be used in the `replaceFn`
|
|
||||||
|
|
||||||
### 0.12.0
|
|
||||||
|
|
||||||
- Add `replaceFn` option
|
|
||||||
|
|
||||||
### 0.11.0
|
|
||||||
|
|
||||||
- Allow Autolinker to link fully-capitalized URLs/Emails/Twitter handles.
|
|
||||||
|
|
||||||
### 0.10.1
|
|
||||||
|
|
||||||
- Added fix to not autolink strings like "version:1.0", which were accidentally being interpreted as a protocol:domain string.
|
|
||||||
|
|
||||||
### 0.10.0
|
|
||||||
|
|
||||||
- Added support for protocol-relative URLs (ex: `//google.com`, which will effectively either have the `http://` or `https://`
|
|
||||||
protocol depending on the protocol that is hosting the website)
|
|
||||||
|
|
||||||
### 0.9.4
|
|
||||||
|
|
||||||
- Fixed an issue where a string in the form of `abc:def` would be autolinked as a protocol and domain name URL. Autolinker now
|
|
||||||
requires the domain name to have at least one period in it to be considered.
|
|
||||||
|
|
||||||
### 0.9.3
|
|
||||||
|
|
||||||
- Fixed an issue where Twitter handles wouldn't be autolinked if they existed as the sole entity within parenthesis or brackets
|
|
||||||
(thanks [@busticated](https://github.com/busticated) for pointing this out and providing unit tests)
|
|
||||||
|
|
||||||
### 0.9.2
|
|
||||||
|
|
||||||
- Fixed an issue with nested tags within an existing <a> tag, where the nested tags' inner text would be accidentally
|
|
||||||
removed from the output (thanks [@mjsabin01](https://github.com/mjsabin01))
|
|
||||||
|
|
||||||
### 0.9.1
|
|
||||||
|
|
||||||
- Added a patch to attempt to better handle extraneous </a> tags in the input string if any exist. This is for when the
|
|
||||||
input may have some invalid markup (for instance, on sites which allow user comments, blog posts, etc.).
|
|
||||||
|
|
||||||
### 0.9.0
|
|
||||||
|
|
||||||
- Added better support for the processing of existing HTML in the input string. Now handles namespaced tags, and attribute names
|
|
||||||
with dashes or any other Unicode character (thanks [@aziraphale](https://github.com/aziraphale))
|
|
||||||
|
|
||||||
### 0.8.0
|
|
||||||
|
|
||||||
- Added `className` option for easily styling produced links (thanks [@busticated](https://github.com/busticated))
|
|
||||||
- Refactored into a JS class. Autolinker can now be instantiated using:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var autolinker = new Autolinker( { newWindow: false, truncate: 25 } );
|
|
||||||
|
|
||||||
autolinker.link( "Check out http://www.yahoo.com/some/long/path/to/a/file" );
|
|
||||||
// Produces: "Check out <a href="http://www.yahoo.com/some/long/path/to/a/file">yahoo.com/some/long/pat..</a>"
|
|
||||||
```
|
|
||||||
|
|
||||||
This allows options to be set on a single instance, and used throughout a codebase by injecting the `autolinker` instance as a dependency to the modules/classes that use it. (Note: Autolinker may still be used with the static `Autolinker.link()` method as was previously available as well.)
|
|
||||||
|
|
||||||
### 0.7.0
|
|
||||||
|
|
||||||
- Changed build system to Grunt.
|
|
||||||
- Added AMD and CommonJS module loading support (ex: RequireJS, and Node.js's module loader).
|
|
||||||
- Added command line Jasmine test runner (`grunt test`)
|
|
||||||
- Upgraded Jasmine from 1.3.1 to 2.0
|
|
||||||
- Added license header to dist files.
|
|
||||||
|
|
||||||
(Thanks to [@busticated](https://github.com/busticated)!)
|
|
||||||
|
|
||||||
### 0.6.1
|
|
||||||
|
|
||||||
- Added LICENSE file to repository.
|
|
||||||
|
|
||||||
### 0.6.0
|
|
||||||
|
|
||||||
- Added options for granular control of which types are linked (urls, email addresses, and/or twitter handles).
|
|
||||||
(thanks [@aziraphale](https://github.com/aziraphale))
|
|
||||||
|
|
||||||
### 0.5.0
|
|
||||||
|
|
||||||
- Simplified the path / query string / hash processing into a single regular expression instead of 3 separate ones.
|
|
||||||
- Added support for parenthesis in URLs, such as: `en.wikipedia.org/wiki/IANA_(disambiguation)` (thanks [@dandv](https://github.com/dandv))
|
|
||||||
- Add all known top-level domains (TLDs) (thanks [@wouter0100](https://github.com/wouter0100))
|
|
||||||
|
|
||||||
### 0.4.0
|
|
||||||
|
|
||||||
Merged pull requests from [@afeld](https://github.com/afeld):
|
|
||||||
|
|
||||||
- strip protocol and 'www.' by default - fixes #1
|
|
||||||
- truncate URLs from the end
|
|
||||||
- make simpler regex for detecting prefix
|
|
||||||
- remove trailing slashes from URLs, and handle periods at the end of paths
|
|
||||||
- re-use domain+TLD regexes for email matching
|
|
||||||
- add .me and .io to list of TLDs
|
|
||||||
|
|
||||||
Thanks Aidan :)
|
|
||||||
|
|
||||||
### 0.3.1
|
|
||||||
|
|
||||||
- Fixed an issue with handling nested HTML tags within anchor tags.
|
|
||||||
|
|
||||||
### 0.3
|
|
||||||
|
|
||||||
- Implemented the `truncate` option.
|
|
||||||
|
|
||||||
### 0.2
|
|
||||||
|
|
||||||
- Implemented autolinking Twitter handles.
|
|
||||||
|
|
||||||
### 0.1
|
|
||||||
|
|
||||||
* Initial implementation, which autolinks URLs and email addresses. Working on linking Twitter handles.
|
|
||||||
|
|
|
||||||
1259
vendors/Autolinker/_/Autolinker.js
vendored
1259
vendors/Autolinker/_/Autolinker.js
vendored
File diff suppressed because it is too large
Load diff
4
vendors/Autolinker/_/Autolinker.min.js
vendored
4
vendors/Autolinker/_/Autolinker.min.js
vendored
File diff suppressed because one or more lines are too long
95
vendors/Autolinker/_/README.md
vendored
95
vendors/Autolinker/_/README.md
vendored
|
|
@ -70,6 +70,9 @@ var autolinker = new Autolinker( [ options ] );
|
||||||
var linkedText = autolinker.link( textToAutoLink );
|
var linkedText = autolinker.link( textToAutoLink );
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: if using the same options to autolink multiple pieces of html/text, it is slightly more efficient to create a single
|
||||||
|
Autolinker instance, and run the `link()` method repeatedly (i.e. use the "class" form above).
|
||||||
|
|
||||||
|
|
||||||
#### Example:
|
#### Example:
|
||||||
|
|
||||||
|
|
@ -105,6 +108,10 @@ These are the options which may be specified for linking. These are specified by
|
||||||
`true` to have email addresses auto-linked, `false` to skip auto-linking of email addresses. Defaults to `true`.<br /><br />
|
`true` to have email addresses auto-linked, `false` to skip auto-linking of email addresses. Defaults to `true`.<br /><br />
|
||||||
- **twitter** : Boolean<br />
|
- **twitter** : Boolean<br />
|
||||||
`true` to have Twitter handles auto-linked, `false` to skip auto-linking of Twitter handles. Defaults to `true`.
|
`true` to have Twitter handles auto-linked, `false` to skip auto-linking of Twitter handles. Defaults to `true`.
|
||||||
|
- **replaceFn** : Function<br />
|
||||||
|
A function to use to programmatically make replacements of matches in the input string, one at a time. See the section
|
||||||
|
<a href="#custom-replacement-function">Custom Replacement Function</a> for more details.
|
||||||
|
|
||||||
|
|
||||||
For example, if you wanted to disable links from opening in new windows, you could do:
|
For example, if you wanted to disable links from opening in new windows, you could do:
|
||||||
|
|
||||||
|
|
@ -146,8 +153,96 @@ autolinker.link( "Go to www.google.com" );
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Custom Replacement Function
|
||||||
|
|
||||||
|
A custom replacement function (`replaceFn`) may be provided to replace url/email/twitter matches on an individual basis, based
|
||||||
|
on the return from this function.
|
||||||
|
|
||||||
|
Full example, for purposes of documenting the API:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var input = "..."; // string with URLs, Email Addresses, and Twitter Handles
|
||||||
|
|
||||||
|
var linkedText = Autolinker.link( input, {
|
||||||
|
replaceFn : function( autolinker, match ) {
|
||||||
|
console.log( "href = ", match.getAnchorHref() );
|
||||||
|
console.log( "text = ", match.getAnchorText() );
|
||||||
|
|
||||||
|
switch( match.getType() ) {
|
||||||
|
case 'url' :
|
||||||
|
console.log( "url: ", match.getUrl() );
|
||||||
|
|
||||||
|
if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) {
|
||||||
|
var tag = autolinker.getTagBuilder().build( match ); // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes
|
||||||
|
tag.setAttr( 'rel', 'nofollow' );
|
||||||
|
tag.addClass( 'external-link' );
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return true; // let Autolinker perform its normal anchor tag replacement
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'email' :
|
||||||
|
var email = match.getEmail();
|
||||||
|
console.log( "email: ", email );
|
||||||
|
|
||||||
|
if( email === "my@own.address" ) {
|
||||||
|
return false; // don't auto-link this particular email address; leave as-is
|
||||||
|
} else {
|
||||||
|
return; // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`)
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'twitter' :
|
||||||
|
var twitterHandle = match.getTwitterHandle();
|
||||||
|
console.log( twitterHandle );
|
||||||
|
|
||||||
|
return '<a href="http://newplace.to.link.twitter.handles.to/">' + twitterHandle + '</a>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The function is provided two arguments:
|
||||||
|
|
||||||
|
1. The Autolinker instance that is performing replacements. This can be used to query the options that the Autolinker
|
||||||
|
instance is configured with, or to retrieve its TagBuilder instance (via `autolinker.getTagBuilder()`).
|
||||||
|
2. An `Autolinker.match.Match` object which details the match that is to be replaced.
|
||||||
|
|
||||||
|
|
||||||
|
A replacement of the match is made based on the return value of the function. The following return values may be provided:
|
||||||
|
|
||||||
|
- No return value (`undefined`), or `true` (Boolean): Delegate back to Autolinker to replace the match as it normally would.
|
||||||
|
- `false` (Boolean): Do not replace the current match at all - leave as-is.
|
||||||
|
- Any String: If a string is returned from the function, the string will be used directly as the replacement HTML for
|
||||||
|
the match.
|
||||||
|
- An `Autolinker.HtmlTag` instance, which can be used to build/modify an HTML tag before writing out its HTML text.
|
||||||
|
|
||||||
|
|
||||||
|
## Full API Docs
|
||||||
|
|
||||||
|
The full API docs for Autolinker may be referenced at: [http://gregjacobs.github.io/Autolinker.js/docs/](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker)
|
||||||
|
|
||||||
|
|
||||||
## Changelog:
|
## Changelog:
|
||||||
|
|
||||||
|
### 0.12.3
|
||||||
|
|
||||||
|
- Add `Autolinker.match.Match#getMatchedText` method
|
||||||
|
|
||||||
|
### 0.12.2
|
||||||
|
|
||||||
|
- Add documentation generation, and update inline documentation.
|
||||||
|
|
||||||
|
### 0.12.1
|
||||||
|
|
||||||
|
- Expose the `Autolinker.HtmlTag` class, and allow it to be used in the `replaceFn`
|
||||||
|
|
||||||
|
### 0.12.0
|
||||||
|
|
||||||
|
- Add `replaceFn` option
|
||||||
|
|
||||||
### 0.11.0
|
### 0.11.0
|
||||||
|
|
||||||
- Allow Autolinker to link fully-capitalized URLs/Emails/Twitter handles.
|
- Allow Autolinker to link fully-capitalized URLs/Emails/Twitter handles.
|
||||||
|
|
|
||||||
1020
vendors/Autolinker/_/_/Autolinker.js
vendored
Normal file
1020
vendors/Autolinker/_/_/Autolinker.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
10
vendors/Autolinker/_/_/Autolinker.min.js
vendored
Normal file
10
vendors/Autolinker/_/_/Autolinker.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
22
vendors/Autolinker/_/_/LICENSE
vendored
Normal file
22
vendors/Autolinker/_/_/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Gregory Jacobs (http://greg-jacobs.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
255
vendors/Autolinker/_/_/README.md
vendored
Normal file
255
vendors/Autolinker/_/_/README.md
vendored
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
# Autolinker.js
|
||||||
|
|
||||||
|
Because I had so much trouble finding a good autolinking implementation out in the wild, I decided to roll my own. It
|
||||||
|
seemed that everything I found out there was either an implementation that didn't cover every case, or was just limited
|
||||||
|
in one way or another.
|
||||||
|
|
||||||
|
So, this utility attempts to handle everything. It:
|
||||||
|
|
||||||
|
- Autolinks URLs, whether or not they start with the protocol (i.e. 'http://'). In other words, it will automatically link the
|
||||||
|
text "google.com", as well as "http://google.com".
|
||||||
|
- Will properly handle URLs with special characters
|
||||||
|
- Will properly handle URLs with query parameters or a named anchor (i.e. hash)
|
||||||
|
- Will autolink email addresses.
|
||||||
|
- Will autolink Twitter handles.
|
||||||
|
- Will properly handle HTML input. The utility will not change the `href` attribute inside anchor (<a>) tags (or any other
|
||||||
|
tag/attribute for that matter), and will not accidentally wrap the inner text of an anchor tag with a new one (which would cause
|
||||||
|
doubly-nested anchor tags).
|
||||||
|
|
||||||
|
Hope that this utility helps you as well!
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
#### Download
|
||||||
|
|
||||||
|
Simply clone or download the zip of the project, and link to either `dist/Autolinker.js` or `dist/Autolinker.min.js` with a script tag:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="path/to/Autolinker.min.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using with the [Bower](http://bower.io) package manager:
|
||||||
|
|
||||||
|
Command line:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
bower install Autolinker.js --save
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using with [Node.js](http://nodejs.org) via [npm](https://www.npmjs.org/):
|
||||||
|
|
||||||
|
Command Line:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install autolinker --save
|
||||||
|
```
|
||||||
|
|
||||||
|
JavaScript:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var Autolinker = require( 'autolinker' );
|
||||||
|
// note: npm wants an all-lowercase package name, but the utility is a class and should be
|
||||||
|
// aliased with a captial letter
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Using the static `link()` method:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var linkedText = Autolinker.link( textToAutolink[, options] );
|
||||||
|
```
|
||||||
|
|
||||||
|
Using as a class:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var autolinker = new Autolinker( [ options ] );
|
||||||
|
|
||||||
|
var linkedText = autolinker.link( textToAutoLink );
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var linkedText = Autolinker.link( "Check out google.com", { className: "myLink" } );
|
||||||
|
// Produces: "Check out <a class="myLink myLink-url" href="http://google.com" target="_blank">google.com</a>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
These are the options which may be specified for linking. These are specified by providing an Object as the second parameter to `Autolinker.link()`. These include:
|
||||||
|
|
||||||
|
- **newWindow** : Boolean<br />
|
||||||
|
`true` to have the links should open in a new window when clicked, `false` otherwise. Defaults to `true`.<br /><br />
|
||||||
|
- **stripPrefix** : Boolean<br />
|
||||||
|
`true` to have the 'http://' or 'https://' and/or the 'www.' stripped from the beginning of links, `false` otherwise. Defaults to `true`.<br /><br />
|
||||||
|
- **truncate** : Number<br />
|
||||||
|
A number for how many characters long URLs/emails/twitter handles should be truncated to inside the text of a link. If the URL/email/twitter is over the number of characters, it will be truncated to this length by replacing the end of the string with a two period ellipsis ('..').<br /><br />
|
||||||
|
Example: a url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters may look like this: 'yahoo.com/some/long/pat..'<br />
|
||||||
|
- **className** : String<br />
|
||||||
|
A CSS class name to add to the generated anchor tags. This class will be added to all links, as well as this class
|
||||||
|
plus "url"/"email"/"twitter" suffixes for styling url/email/twitter links differently.
|
||||||
|
|
||||||
|
For example, if this config is provided as "myLink", then:
|
||||||
|
|
||||||
|
1) URL links will have the CSS classes: "myLink myLink-url"<br />
|
||||||
|
2) Email links will have the CSS classes: "myLink myLink-email", and<br />
|
||||||
|
3) Twitter links will have the CSS classes: "myLink myLink-twitter"<br />
|
||||||
|
|
||||||
|
- **urls** : Boolean<br />
|
||||||
|
`true` to have URLs auto-linked, `false` to skip auto-linking of URLs. Defaults to `true`.<br />
|
||||||
|
- **email** : Boolean<br />
|
||||||
|
`true` to have email addresses auto-linked, `false` to skip auto-linking of email addresses. Defaults to `true`.<br /><br />
|
||||||
|
- **twitter** : Boolean<br />
|
||||||
|
`true` to have Twitter handles auto-linked, `false` to skip auto-linking of Twitter handles. Defaults to `true`.
|
||||||
|
|
||||||
|
For example, if you wanted to disable links from opening in new windows, you could do:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var linkedText = Autolinker.link( "Check out google.com", { newWindow: false } );
|
||||||
|
// Produces: "Check out <a href="http://google.com">google.com</a>"
|
||||||
|
```
|
||||||
|
|
||||||
|
And if you wanted to truncate the length of URLs (while also not opening in a new window), you could do:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var linkedText = Autolinker.link( "http://www.yahoo.com/some/long/path/to/a/file", { truncate: 25, newWindow: false } );
|
||||||
|
// Produces: "<a href="http://www.yahoo.com/some/long/path/to/a/file">yahoo.com/some/long/pat..</a>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## More Examples
|
||||||
|
One could update an entire DOM element that has unlinked text to auto-link them as such:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var myTextEl = document.getElementById( 'text' );
|
||||||
|
myTextEl.innerHTML = Autolinker.link( myTextEl.innerHTML );
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the same pre-configured Autolinker instance in multiple locations of a codebase (usually by dependency injection):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var autolinker = new Autolinker( { newWindow: false, truncate: 25 } );
|
||||||
|
|
||||||
|
//...
|
||||||
|
|
||||||
|
autolinker.link( "Check out http://www.yahoo.com/some/long/path/to/a/file" );
|
||||||
|
// Produces: "Check out <a href="http://www.yahoo.com/some/long/path/to/a/file">yahoo.com/some/long/pat..</a>"
|
||||||
|
|
||||||
|
//...
|
||||||
|
|
||||||
|
autolinker.link( "Go to www.google.com" );
|
||||||
|
// Produces: "Go to <a href="http://www.google.com">google.com</a>"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Changelog:
|
||||||
|
|
||||||
|
### 0.11.0
|
||||||
|
|
||||||
|
- Allow Autolinker to link fully-capitalized URLs/Emails/Twitter handles.
|
||||||
|
|
||||||
|
### 0.10.1
|
||||||
|
|
||||||
|
- Added fix to not autolink strings like "version:1.0", which were accidentally being interpreted as a protocol:domain string.
|
||||||
|
|
||||||
|
### 0.10.0
|
||||||
|
|
||||||
|
- Added support for protocol-relative URLs (ex: `//google.com`, which will effectively either have the `http://` or `https://`
|
||||||
|
protocol depending on the protocol that is hosting the website)
|
||||||
|
|
||||||
|
### 0.9.4
|
||||||
|
|
||||||
|
- Fixed an issue where a string in the form of `abc:def` would be autolinked as a protocol and domain name URL. Autolinker now
|
||||||
|
requires the domain name to have at least one period in it to be considered.
|
||||||
|
|
||||||
|
### 0.9.3
|
||||||
|
|
||||||
|
- Fixed an issue where Twitter handles wouldn't be autolinked if they existed as the sole entity within parenthesis or brackets
|
||||||
|
(thanks [@busticated](https://github.com/busticated) for pointing this out and providing unit tests)
|
||||||
|
|
||||||
|
### 0.9.2
|
||||||
|
|
||||||
|
- Fixed an issue with nested tags within an existing <a> tag, where the nested tags' inner text would be accidentally
|
||||||
|
removed from the output (thanks [@mjsabin01](https://github.com/mjsabin01))
|
||||||
|
|
||||||
|
### 0.9.1
|
||||||
|
|
||||||
|
- Added a patch to attempt to better handle extraneous </a> tags in the input string if any exist. This is for when the
|
||||||
|
input may have some invalid markup (for instance, on sites which allow user comments, blog posts, etc.).
|
||||||
|
|
||||||
|
### 0.9.0
|
||||||
|
|
||||||
|
- Added better support for the processing of existing HTML in the input string. Now handles namespaced tags, and attribute names
|
||||||
|
with dashes or any other Unicode character (thanks [@aziraphale](https://github.com/aziraphale))
|
||||||
|
|
||||||
|
### 0.8.0
|
||||||
|
|
||||||
|
- Added `className` option for easily styling produced links (thanks [@busticated](https://github.com/busticated))
|
||||||
|
- Refactored into a JS class. Autolinker can now be instantiated using:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var autolinker = new Autolinker( { newWindow: false, truncate: 25 } );
|
||||||
|
|
||||||
|
autolinker.link( "Check out http://www.yahoo.com/some/long/path/to/a/file" );
|
||||||
|
// Produces: "Check out <a href="http://www.yahoo.com/some/long/path/to/a/file">yahoo.com/some/long/pat..</a>"
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows options to be set on a single instance, and used throughout a codebase by injecting the `autolinker` instance as a dependency to the modules/classes that use it. (Note: Autolinker may still be used with the static `Autolinker.link()` method as was previously available as well.)
|
||||||
|
|
||||||
|
### 0.7.0
|
||||||
|
|
||||||
|
- Changed build system to Grunt.
|
||||||
|
- Added AMD and CommonJS module loading support (ex: RequireJS, and Node.js's module loader).
|
||||||
|
- Added command line Jasmine test runner (`grunt test`)
|
||||||
|
- Upgraded Jasmine from 1.3.1 to 2.0
|
||||||
|
- Added license header to dist files.
|
||||||
|
|
||||||
|
(Thanks to [@busticated](https://github.com/busticated)!)
|
||||||
|
|
||||||
|
### 0.6.1
|
||||||
|
|
||||||
|
- Added LICENSE file to repository.
|
||||||
|
|
||||||
|
### 0.6.0
|
||||||
|
|
||||||
|
- Added options for granular control of which types are linked (urls, email addresses, and/or twitter handles).
|
||||||
|
(thanks [@aziraphale](https://github.com/aziraphale))
|
||||||
|
|
||||||
|
### 0.5.0
|
||||||
|
|
||||||
|
- Simplified the path / query string / hash processing into a single regular expression instead of 3 separate ones.
|
||||||
|
- Added support for parenthesis in URLs, such as: `en.wikipedia.org/wiki/IANA_(disambiguation)` (thanks [@dandv](https://github.com/dandv))
|
||||||
|
- Add all known top-level domains (TLDs) (thanks [@wouter0100](https://github.com/wouter0100))
|
||||||
|
|
||||||
|
### 0.4.0
|
||||||
|
|
||||||
|
Merged pull requests from [@afeld](https://github.com/afeld):
|
||||||
|
|
||||||
|
- strip protocol and 'www.' by default - fixes #1
|
||||||
|
- truncate URLs from the end
|
||||||
|
- make simpler regex for detecting prefix
|
||||||
|
- remove trailing slashes from URLs, and handle periods at the end of paths
|
||||||
|
- re-use domain+TLD regexes for email matching
|
||||||
|
- add .me and .io to list of TLDs
|
||||||
|
|
||||||
|
Thanks Aidan :)
|
||||||
|
|
||||||
|
### 0.3.1
|
||||||
|
|
||||||
|
- Fixed an issue with handling nested HTML tags within anchor tags.
|
||||||
|
|
||||||
|
### 0.3
|
||||||
|
|
||||||
|
- Implemented the `truncate` option.
|
||||||
|
|
||||||
|
### 0.2
|
||||||
|
|
||||||
|
- Implemented autolinking Twitter handles.
|
||||||
|
|
||||||
|
### 0.1
|
||||||
|
|
||||||
|
* Initial implementation, which autolinks URLs and email addresses. Working on linking Twitter handles.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue