diff --git a/js/plugins.js b/js/plugins.js
index fd9bf51..296fa0e 100644
--- a/js/plugins.js
+++ b/js/plugins.js
@@ -10,15 +10,42 @@ var plugins = angular.module('plugins', []);
/*
* Definition of a user provided plugin with sensible default values
*
- * User plugins are created by providing a contentForMessage function
- * that parses a string and return any additional content.
+ * User plugins are created by providing a name and a contentForMessage
+ * function that parses a string and returns any additional content.
*/
-var Plugin = function(contentForMessage) {
-
+var Plugin = function(name, contentForMessage) {
return {
contentForMessage: contentForMessage,
exclusive: false,
- name: "additional content"
+ name: name
+ };
+};
+
+
+// Regular expression that detects URLs for UrlPlugin
+var urlRegexp = /(?:ftp|https?):\/\/\S*[^\s.;,(){}<>]/g;
+/*
+ * Definition of a user provided plugin that consumes URLs
+ *
+ * URL plugins are created by providing a name and a function that
+ * that parses a URL and returns any additional content.
+ */
+var UrlPlugin = function(name, urlCallback) {
+ return {
+ contentForMessage: function(message) {
+ var urls = message.match(urlRegexp);
+ var content = [];
+
+ for (var i = 0; urls && i < urls.length; i++) {
+ var result = urlCallback(urls[i]);
+ if (result) {
+ content.push(result);
+ }
+ }
+ return content;
+ },
+ exclusive: false,
+ name: name
};
};
@@ -32,8 +59,6 @@ var Plugin = function(contentForMessage) {
*/
plugins.service('plugins', ['userPlugins', '$sce', function(userPlugins, $sce) {
- var nsfwRegexp = new RegExp('nsfw', 'i');
-
/*
* Defines the plugin manager object
*/
@@ -52,6 +77,8 @@ plugins.service('plugins', ['userPlugins', '$sce', function(userPlugins, $sce) {
}
};
+ var nsfwRegexp = new RegExp('nsfw', 'i');
+
/*
* Iterates through all the registered plugins
* and run their contentForMessage function.
@@ -146,23 +173,6 @@ plugins.factory('userPlugins', function() {
document.body.appendChild(script);
};
- var urlRegexp = new RegExp(/(?:ftp|https?):\/\/\S*[^\s.;,(){}<>]/g);
-
- var urlPlugin = function(callback) {
- return function(message) {
- var urls = message.match(urlRegexp);
- var content = [];
-
- for (var i = 0; urls && i < urls.length; i++) {
- var result = callback(urls[i]);
- if (result) {
- content.push(result);
- }
- }
- return content;
- };
- };
-
/*
* Spotify Embedded Player
*
@@ -170,7 +180,7 @@ plugins.factory('userPlugins', function() {
*
*/
- var spotifyPlugin = new Plugin(function(message) {
+ var spotifyPlugin = new Plugin('Spotify track', function(message) {
var content = [];
var addMatch = function(match) {
for (var i = 0; match && i < match.length; i++) {
@@ -182,39 +192,29 @@ plugins.factory('userPlugins', function() {
addMatch(message.match(/open.spotify.com\/track\/([a-zA-Z-0-9]{22})/g));
return content;
});
- spotifyPlugin.name = 'Spotify track';
/*
* YouTube Embedded Player
*
* See: https://developers.google.com/youtube/player_parameters
*/
- var youtubePlugin = new Plugin(function(message) {
+ var youtubePlugin = new UrlPlugin('YouTube video', function(url) {
+ var regex = /(?:youtube.com|youtu.be)\/(?:v\/|embed\/|watch(?:\?v=|\/))?([a-zA-Z0-9-]+)/i,
+ match = url.match(regex);
- var regExp = /(?:https?:\/\/)?(?:www\.)?(?:youtube.com|youtu.be)\/(?:v\/|embed\/|watch(?:\?v=|\/))?([a-zA-Z0-9-]+)/gm;
- var match = regExp.exec(message);
- var content = [];
-
- // iterate over all matches
- while (match !== null){
- var token = match[1];
- var embedurl = "https://www.youtube.com/embed/" + token + "?html5=1&iv_load_policy=3&modestbranding=1&rel=0&showinfo=0";
- content.push('');
- // next match
- match = regExp.exec(message);
+ if (match){
+ var token = match[1],
+ embedurl = "https://www.youtube.com/embed/" + token + "?html5=1&iv_load_policy=3&modestbranding=1&rel=0&showinfo=0";
+ return '';
}
-
- return content;
});
- youtubePlugin.name = 'YouTube video';
/*
* Dailymotion Embedded Player
*
* See: http://www.dailymotion.com/doc/api/player.html
*/
- var dailymotionPlugin = new Plugin(function(message) {
-
+ var dailymotionPlugin = new Plugin('Dailymotion video', function(message) {
var rPath = /dailymotion.com\/.*video\/([^_?# ]+)/;
var rAnchor = /dailymotion.com\/.*#video=([^_& ]+)/;
var rShorten = /dai.ly\/([^_?# ]+)/;
@@ -228,13 +228,11 @@ plugins.factory('userPlugins', function() {
return null;
});
- dailymotionPlugin.name = 'Dailymotion video';
/*
* AlloCine Embedded Player
*/
- var allocinePlugin = new Plugin(function(message) {
-
+ var allocinePlugin = new Plugin('AlloCine video', function(message) {
var rVideokast = /allocine.fr\/videokast\/video-(\d+)/;
var rCmedia = /allocine.fr\/.*cmedia=(\d+)/;
@@ -247,169 +245,148 @@ plugins.factory('userPlugins', function() {
return null;
});
- allocinePlugin.name = 'AlloCine video';
/*
* Image Preview
*/
- var imagePlugin = new Plugin(
- urlPlugin(function(url) {
- var embed = false;
- // Check the get parameters as well, they might contain an image to load
- var segments = url.split(/[?&]/).forEach(function(param) {
- if (param.match(/\.(png|gif|jpg|jpeg)(:(small|medium|large))?$/i)) {
- embed = true;
- }
- });
- if (embed) {
- /* A fukung.net URL may end by an image extension but is not a direct link. */
- if (url.indexOf("^https?://fukung.net/v/") != -1) {
- url = url.replace(/.*\//, "http://media.fukung.net/imgs/");
- } else if (url.match(/^http:\/\/(i\.)?imgur\.com\//i)) {
- // remove protocol specification to load over https if used by g-b
- url = url.replace(/http:/, "");
- } else if (url.match(/^https:\/\/www\.dropbox\.com\/s\/[a-z0-9]+\/[^?]+$/i)) {
- // Dropbox requires a get parameter, dl=1
- url = url + "?dl=1";
- }
-
- return '';
+ var imagePlugin = new UrlPlugin('image', function(url) {
+ var embed = false;
+ // Check the get parameters as well, they might contain an image to load
+ var segments = url.split(/[?&]/).forEach(function(param) {
+ if (param.match(/\.(png|gif|jpg|jpeg)(:(small|medium|large))?$/i)) {
+ embed = true;
}
- })
- );
- imagePlugin.name = 'image';
+ });
+ if (embed) {
+ /* A fukung.net URL may end by an image extension but is not a direct link. */
+ if (url.indexOf("^https?://fukung.net/v/") != -1) {
+ url = url.replace(/.*\//, "http://media.fukung.net/imgs/");
+ } else if (url.match(/^http:\/\/(i\.)?imgur\.com\//i)) {
+ // remove protocol specification to load over https if used by g-b
+ url = url.replace(/http:/, "");
+ } else if (url.match(/^https:\/\/www\.dropbox\.com\/s\/[a-z0-9]+\/[^?]+$/i)) {
+ // Dropbox requires a get parameter, dl=1
+ // TODO strip an existing dl=0 parameter
+ url = url + "?dl=1";
+ }
+
+ return '
';
+ }
+ });
/*
* Cloud Music Embedded Players
*/
- var cloudmusicPlugin = new Plugin(
- urlPlugin(function(url) {
- /* SoundCloud http://help.soundcloud.com/customer/portal/articles/247785-what-widgets-can-i-use-from-soundcloud- */
- if (url.match(/^https?:\/\/soundcloud.com\//)) {
- return '';
- }
+ var cloudmusicPlugin = new UrlPlugin('cloud music', function(url) {
+ /* SoundCloud http://help.soundcloud.com/customer/portal/articles/247785-what-widgets-can-i-use-from-soundcloud- */
+ if (url.match(/^https?:\/\/soundcloud.com\//)) {
+ return '';
+ }
- /* MixCloud */
- if (url.match(/^https?:\/\/([a-z]+\.)?mixcloud.com\//)) {
- return '';
- }
- })
- );
- cloudmusicPlugin.name = 'cloud music';
+ /* MixCloud */
+ if (url.match(/^https?:\/\/([a-z]+\.)?mixcloud.com\//)) {
+ return '';
+ }
+ });
/*
* Google Maps
*/
- var googlemapPlugin = new Plugin(
- urlPlugin(function(url) {
- if (url.match(/^https?:\/\/maps\.google\./i) || url.match(/^https?:\/\/(?:[\w]+\.)?google\.[\w]+\/maps/i)) {
- return '';
- }
- })
- );
- googlemapPlugin.name = 'Google Map';
+ var googlemapPlugin = new UrlPlugin('Google Map', function(url) {
+ if (url.match(/^https?:\/\/maps\.google\./i) || url.match(/^https?:\/\/(?:[\w]+\.)?google\.[\w]+\/maps/i)) {
+ return '';
+ }
+ });
/*
* Asciinema plugin
*/
- var asciinemaPlugin = new Plugin(function(message) {
-
- var regexp = /^https?:\/\/(www\.)?asciinema.org\/a\/(\d+)/;
- var match = message.match(regexp);
+ var asciinemaPlugin = new UrlPlugin('ascii cast', function(url) {
+ var regexp = /^https?:\/\/(?:www\.)?asciinema.org\/a\/(\d+)/i,
+ match = url.match(regexp);
if (match) {
- var id = match[3];
- return "";
+ var id = match[1];
+ return function() {
+ var element = this.getElement();
+ var scriptElem = document.createElement('script');
+ scriptElem.src = 'https://asciinema.org/a/' + id + '.js';
+ scriptElem.id = 'asciicast-' + id;
+ scriptElem.async = true;
+ element.appendChild(scriptElem);
+ };
}
});
- asciinemaPlugin.name = "ascii cast";
- var yrPlugin = new Plugin(
- urlPlugin(function(url) {
- var regexp = /^https?:\/\/(?:www\.)?yr\.no\/(place|stad|sted|sadji|paikka)\/(([^\s.;,(){}<>\/]+\/){3,})/;
- var match = url.match(regexp);
- if (match) {
- var language = match[1];
- var location = match[2];
- var city = match[match.length - 1].slice(0, -1);
- url = "http://www.yr.no/" + language + "/" + location + "avansert_meteogram.png";
- return "
";
- }
- })
- );
- yrPlugin.name = "meteogram";
+ var yrPlugin = new UrlPlugin('meteogram', function(url) {
+ var regexp = /^https?:\/\/(?:www\.)?yr\.no\/(place|stad|sted|sadji|paikka)\/(([^\s.;,(){}<>\/]+\/){3,})/;
+ var match = url.match(regexp);
+ if (match) {
+ var language = match[1];
+ var location = match[2];
+ var city = match[match.length - 1].slice(0, -1);
+ url = "http://www.yr.no/" + language + "/" + location + "avansert_meteogram.png";
+ return "
";
+ }
+ });
// Embed GitHub gists
- var gistPlugin = new Plugin(
- urlPlugin(function(url) {
- var regexp = /^https:\/\/gist\.github.com\/[^.?]+/i;
- var match = url.match(regexp);
- if (match) {
- // get the URL from the match to trim away pseudo file endings and request parameters
- url = match[0] + '.json';
- // load gist asynchronously -- return a function here
- return function() {
- var element = this.getElement();
- jsonp(url, function(data) {
- // Add the gist stylesheet only once
- if (document.querySelectorAll('link[rel=stylesheet][href="' + data.stylesheet + '"]').length < 1) {
- var stylesheet = '';
- document.getElementsByTagName('head')[0].innerHTML += stylesheet;
- }
- element.innerHTML = '