diff --git a/angular-linkify.js b/angular-linkify.js
deleted file mode 100644
index a00f413..0000000
--- a/angular-linkify.js
+++ /dev/null
@@ -1,73 +0,0 @@
-angular.module('linkify', []);
-
-angular.module('linkify')
- .filter('linkify', function () {
- 'use strict';
-
- function linkify (_str, type) {
- if (!_str) {
- return;
- }
-
- var _text = _str.replace( /(?:https?\:\/\/|www\.)+(?![^\s]*?")([\w.,@?!^=%&:\/~+#-]*[\w@?!^=%&\/~+#-])?/ig, function(url) {
- var wrap = document.createElement('div');
- var anch = document.createElement('a');
- anch.href = url;
- anch.target = "_blank";
- anch.innerHTML = url;
- wrap.appendChild(anch);
- return wrap.innerHTML;
- });
-
- // bugfix
- if (!_text) {
- return '';
- }
-
- // Twitter
- if (type === 'twitter') {
- _text = _text.replace(/(|\s)*@([\u00C0-\u1FFF\w]+)/g, '$1@$2');
- _text = _text.replace(/(^|\s)*#([\u00C0-\u1FFF\w]+)/g, '$1#$2');
- }
-
-
- // Github
- if (type === 'github') {
- _text = _text.replace(/(|\s)*@(\w+)/g, '$1@$2');
- }
-
- return _text;
- }
-
- //
- return function (text, type) {
- return linkify(text, type);
- };
- })
- .factory('linkify', ['$filter', function ($filter) {
- 'use strict';
-
- function _linkifyAsType (type) {
- return function (str) {(type, str);
- return $filter('linkify')(str, type);
- };
- }
-
- return {
- twitter: _linkifyAsType('twitter'),
- github: _linkifyAsType('github'),
- normal: _linkifyAsType()
- };
- }])
- .directive('linkify', ['$filter', '$timeout', 'linkify', function ($filter, $timeout, linkify) {
- 'use strict';
-
- return {
- restrict: 'A',
- link: function (scope, element, attrs) {
- var type = attrs.linkify || 'normal';
- $timeout(function () { element.html(linkify[type](element.html())); });
- }
- };
- }]);
-
diff --git a/angular-linkify.min.js b/angular-linkify.min.js
deleted file mode 100644
index a0f01ae..0000000
--- a/angular-linkify.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
-angular-linkify - v1.2.0 - 3/5/2015
-Angular filter to linkify urls, "@" usernames, and hashtags.
-Copyright (c) 2015 ; Licensed
-*/
-angular.module("linkify",[]),angular.module("linkify").filter("linkify",function(){"use strict";function linkify(_str,type){if(_str){var _text=_str.replace(/(?:https?\:\/\/|www\.)+(?![^\s]*?")([\w.,@?!^=%&:\/~+#-]*[\w@?!^=%&\/~+#-])?/gi,function(url){var wrap=document.createElement("div"),anch=document.createElement("a");return anch.href=url,anch.target="_blank",anch.innerHTML=url,wrap.appendChild(anch),wrap.innerHTML});return _text?("twitter"===type&&(_text=_text.replace(/(|\s)*@([\u00C0-\u1FFF\w]+)/g,'$1@$2'),_text=_text.replace(/(^|\s)*#([\u00C0-\u1FFF\w]+)/g,'$1#$2')),"github"===type&&(_text=_text.replace(/(|\s)*@(\w+)/g,'$1@$2')),_text):""}}return function(text,type){return linkify(text,type)}}).factory("linkify",["$filter",function($filter){"use strict";function _linkifyAsType(type){return function(str){return $filter("linkify")(str,type)}}return{twitter:_linkifyAsType("twitter"),github:_linkifyAsType("github"),normal:_linkifyAsType()}}]).directive("linkify",["$filter","$timeout","linkify",function($filter,$timeout,linkify){"use strict";return{restrict:"A",link:function(scope,element,attrs){var type=attrs.linkify||"normal";$timeout(function(){element.html(linkify[type](element.html()))})}}}]);
\ No newline at end of file
diff --git a/bower.json b/bower.json
index b2cbbc5..539a865 100644
--- a/bower.json
+++ b/bower.json
@@ -1,7 +1,7 @@
{
"name": "angular-linkify",
"version": "1.2.0",
- "main": "angular-linkify.js",
+ "main": "dist/angular-linkify.js",
"description": "Angular filter to linkify urls, \"@\" usernames, and hashtags.",
"ignore": [
"**/.*",
diff --git a/dist/.gitignore b/dist/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/dist/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/lib/directive.js b/lib/directive.js
new file mode 100644
index 0000000..6d5840f
--- /dev/null
+++ b/lib/directive.js
@@ -0,0 +1,26 @@
+var angular = require('angular');
+var linkifyElement = require('linkifyjs/element');
+
+angular.module('linkify').directive('linkify',[
+ 'linkify',
+ function (linkify) {
+ var defaultOptions = linkify.getOptions() || {};
+
+ var link = function (scope, element) {
+ var options = angular.extend(defaultOptions, scope.options);
+
+ scope.$evalAsync(function () {
+ try {
+ linkifyElement(element[0], options);
+ } catch (e) {}
+ });
+ };
+
+ return {
+ link: link,
+ scope: {
+ options: '=?linkify'
+ }
+ }
+ }
+])
\ No newline at end of file
diff --git a/lib/filter.js b/lib/filter.js
new file mode 100644
index 0000000..ce8cea3
--- /dev/null
+++ b/lib/filter.js
@@ -0,0 +1,14 @@
+'use strict';
+
+var angular = require('angular');
+
+angular.module('linkify')
+ .filter('linkify', [
+ 'linkify',
+ function (linkify) {
+ return function (str, options) {
+ if (!str) { return str; }
+ return linkify.parse(str, options);
+ };
+ }
+ ]);
\ No newline at end of file
diff --git a/lib/index.js b/lib/index.js
new file mode 100644
index 0000000..42f822e
--- /dev/null
+++ b/lib/index.js
@@ -0,0 +1,13 @@
+'use strict';
+
+var angular = require('angular');
+// add configuration for plugins
+var linkifyjs = require('linkifyjs');
+require('linkifyjs/plugins/hashtag')(linkifyjs);
+require('./plugins/mentions')(linkifyjs);
+
+module.exports = angular.module('linkify', []).name;
+
+require('./filter');
+require('./service');
+require('./directive');
\ No newline at end of file
diff --git a/lib/plugins/mentions.js b/lib/plugins/mentions.js
new file mode 100644
index 0000000..5958bb7
--- /dev/null
+++ b/lib/plugins/mentions.js
@@ -0,0 +1,38 @@
+'use strict';
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
+function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function mention(linkify) {
+ var TT = linkify.scanner.TOKENS,
+ // Text tokens
+ MT = linkify.parser.TOKENS,
+ // Multi tokens
+ MultiToken = MT.Base,
+ S_START = linkify.parser.start,
+ S_AT = undefined,
+ S_MENTION = undefined;
+
+ var MENTION = (function (_MultiToken) {
+ _inherits(MENTION, _MultiToken);
+
+ function MENTION(value) {
+ _classCallCheck(this, MENTION);
+
+ _MultiToken.call(this, value);
+ this.type = 'mention';
+ this.isLink = true;
+ }
+
+ return MENTION;
+ })(MultiToken);
+
+ S_AT = new linkify.parser.State();
+ S_MENTION = new linkify.parser.State(MENTION);
+
+ S_START.on(TT.AT, S_AT);
+ S_AT.on(TT.DOMAIN, S_MENTION);
+ S_AT.on(TT.TLD, S_MENTION);
+}
+
+module.exports = mention;
\ No newline at end of file
diff --git a/lib/service.js b/lib/service.js
new file mode 100644
index 0000000..fb7f393
--- /dev/null
+++ b/lib/service.js
@@ -0,0 +1,38 @@
+'use strict';
+
+var linkifyHtml = require('linkifyjs/html');
+var angular = require('angular');
+
+angular.module('linkify')
+ .provider('linkify', function () {
+ var defaultOptions = {
+ formatHref: function (value, type) {
+ if (type === 'hashtag') {
+ return 'https://twitter.com/hashtag/' + value.substring(1);
+ }
+ if (type === 'mention') {
+ return 'https://www.github.com/' + value.substring(1);
+ }
+ return value;
+ }
+ };
+
+ this.setOptions = function (options) {
+ defaultOptions = angular.extend(defaultOptions, options);
+ };
+
+ this.$get = [
+ function () {
+ return {
+ parse: function (str, options) {
+ if (!str) { return str; }
+ if (!options) { return linkifyHtml(str, defaultOptions); }
+ return linkifyHtml(str, angular.extend(defaultOptions, options));
+ },
+ getOptions: function () {
+ return defaultOptions;
+ }
+ };
+ }
+ ];
+ });
\ No newline at end of file
diff --git a/package.json b/package.json
index 67da783..32c408e 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,10 @@
{
"name": "angular-linkify",
- "version": "1.2.0",
- "description": "Angular filter to linkify urls, \"@\" usernames, and hashtags.",
- "main": "angular-linkify.js",
- "directories": {
- "test": "test"
- },
+ "version": "2.0.0",
+ "description": "Angular filter to linkify urls, @mentions and #hashtags.",
+ "main": "lib/index.js",
"scripts": {
+ "prepublish": "webpack -p --config webpack.prod.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@@ -21,13 +19,24 @@
"twitter"
],
"author": "Scott Corgan",
- "license": "BSD",
+ "license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/scottcorgan/angular-linkify/issues"
},
"devDependencies": {
- "grunt": "~0.4.1",
- "grunt-contrib-jshint": "~0.6.0",
- "grunt-contrib-uglify": "~0.2.2"
+ "angular-mocks": "^1.5.0",
+ "chai": "^3.5.0",
+ "karma": "^0.13.19",
+ "karma-chai": "^0.1.0",
+ "karma-mocha": "^0.2.1",
+ "karma-webpack": "^1.7.0",
+ "mocha": "^2.4.5",
+ "phantomjs": "^2.1.3",
+ "phantomjs-polyfill": "0.0.1",
+ "webpack": "^1.12.13"
+ },
+ "dependencies": {
+ "angular": "^1.5.0",
+ "linkifyjs": "^2.0.0-beta.9"
}
}
diff --git a/webpack.base.config.js b/webpack.base.config.js
new file mode 100644
index 0000000..5852dfa
--- /dev/null
+++ b/webpack.base.config.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var webpack = require('webpack');
+
+module.exports = {
+ entry: './lib/index.js',
+
+ resolve: {
+ modulesDirectories: ['node_modules', 'bower_components'],
+ extensions: ['', '.js']
+ },
+
+ externals: [
+ {
+ angular: {
+ root: "angular",
+ commonjs2: "angular",
+ commonjs: "angular",
+ amd: "angular"
+ }
+ }
+ ],
+
+ output: {
+ library: 'AngularLinkify',
+ libraryTarget: 'umd',
+ path: './dist',
+ filename: 'angular-linkify.js'
+ },
+
+ module: {
+ loaders: []
+ }
+};
\ No newline at end of file
diff --git a/webpack.dev.config.js b/webpack.dev.config.js
new file mode 100644
index 0000000..078130b
--- /dev/null
+++ b/webpack.dev.config.js
@@ -0,0 +1,8 @@
+'use strict'
+var baseConfig = require('./webpack.base.config.js');
+
+var config = baseConfig;
+
+config.devtool = "inline-source-map";
+
+module.exports = config;
\ No newline at end of file
diff --git a/webpack.prod.config.js b/webpack.prod.config.js
new file mode 100644
index 0000000..98c68bb
--- /dev/null
+++ b/webpack.prod.config.js
@@ -0,0 +1,14 @@
+'use strict'
+
+var webpack = require('webpack');
+var baseConfig = require('./webpack.base.config.js');
+
+var config = baseConfig;
+
+config.plugins = [
+ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
+ new webpack.optimize.DedupePlugin(),
+ new webpack.optimize.UglifyJsPlugin()
+];
+
+module.exports = config;
\ No newline at end of file