diff options
| author | Ken Sheedlo | 2013-08-22 14:56:42 -0600 |
|---|---|---|
| committer | Brian Ford | 2013-09-27 11:50:21 -0700 |
| commit | 6aaae062171bfc8e5046c3eae99bc9d63037120a (patch) | |
| tree | e78b3de544e5f956dcca0b56e5ef335fbf96ec76 /docs | |
| parent | 6a8edc1d43aca7c5a92f86309b1bb1d5f9968442 (diff) | |
| download | angular.js-6aaae062171bfc8e5046c3eae99bc9d63037120a.tar.bz2 | |
feat(docs): linkify error messages on minErr docs pages
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/component-spec/errorLinkFilterSpec.js | 49 | ||||
| -rw-r--r-- | docs/src/templates/js/docs.js | 44 |
2 files changed, 90 insertions, 3 deletions
diff --git a/docs/component-spec/errorLinkFilterSpec.js b/docs/component-spec/errorLinkFilterSpec.js new file mode 100644 index 00000000..36f5f46b --- /dev/null +++ b/docs/component-spec/errorLinkFilterSpec.js @@ -0,0 +1,49 @@ +describe("errorLinkFilter", function () { + + var errorLinkFilter; + + beforeEach(module('docsApp')); + + beforeEach(inject(function ($filter) { + errorLinkFilter = $filter('errorLink'); + })); + + it('should not change text that does not contain links', function () { + expect(errorLinkFilter('This is a test')).toBe('This is a test'); + }); + + it('should find links in text and linkify them', function () { + expect(errorLinkFilter("http://ab/ (http://a/) http://1.2/v:~-123. c")). + toBe('<a href="http://ab/">http://ab/</a> ' + + '(<a href="http://a/">http://a/</a>) ' + + '<a href="http://1.2/v:~-123">http://1.2/v:~-123</a>. c'); + expect(errorLinkFilter(undefined)).not.toBeDefined(); + }); + + it('should handle mailto', function () { + expect(errorLinkFilter("mailto:me@example.com")). + toBe('<a href="mailto:me@example.com">me@example.com</a>'); + expect(errorLinkFilter("me@example.com")). + toBe('<a href="mailto:me@example.com">me@example.com</a>'); + expect(errorLinkFilter("send email to me@example.com, but")). + toBe('send email to <a href="mailto:me@example.com">me@example.com</a>, but'); + }); + + it('should handle target', function () { + expect(errorLinkFilter("http://example.com", "_blank")). + toBe('<a target="_blank" href="http://example.com">http://example.com</a>') + expect(errorLinkFilter("http://example.com", "someNamedIFrame")). + toBe('<a target="someNamedIFrame" href="http://example.com">http://example.com</a>') + }); + + it('should not linkify stack trace URLs', function () { + expect(errorLinkFilter("http://example.com/angular.min.js:42:1337")). + toBe("http://example.com/angular.min.js:42:1337"); + }); + + it('should truncate linked URLs at 60 characters', function () { + expect(errorLinkFilter("http://errors.angularjs.org/very-long-version-string/$injector/nomod?p0=myApp")). + toBe('<a href="http://errors.angularjs.org/very-long-version-string/$injector/nomod?p0=myApp">' + + 'http://errors.angularjs.org/very-long-version-string/$inj...</a>'); + }); +});
\ No newline at end of file diff --git a/docs/src/templates/js/docs.js b/docs/src/templates/js/docs.js index 9b38313b..b8c42ef8 100644 --- a/docs/src/templates/js/docs.js +++ b/docs/src/templates/js/docs.js @@ -1,7 +1,8 @@ var docsApp = { controller: {}, directive: {}, - serviceFactory: {} + serviceFactory: {}, + filter: {} }; docsApp.controller.DocsVersionsCtrl = ['$scope', '$window', 'NG_VERSIONS', 'NG_VERSION', function($scope, $window, NG_VERSIONS, NG_VERSION) { @@ -255,7 +256,40 @@ docsApp.directive.docTutorialReset = function() { }; -docsApp.directive.errorDisplay = ['$location', function ($location) { +docsApp.filter.errorLink = ['$sanitize', function ($sanitize) { + var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/g, + MAILTO_REGEXP = /^mailto:/, + STACK_TRACE_REGEXP = /:\d+:\d+$/; + + var truncate = function (text, nchars) { + if (text.length > nchars) { + return text.substr(0, nchars - 3) + '...'; + } + return text; + }; + + return function (text, target) { + var targetHtml = target ? ' target="' + target + '"' : ''; + + if (!text) return text; + + return $sanitize(text.replace(LINKY_URL_REGEXP, function (url) { + if (STACK_TRACE_REGEXP.test(url)) { + return url; + } + + // if we did not match ftp/http/mailto then assume mailto + if (!/^((ftp|https?):\/\/|mailto:)/.test(url)) url = 'mailto:' + url; + + return '<a' + targetHtml + ' href="' + url +'">' + + truncate(url.replace(MAILTO_REGEXP, ''), 60) + + '</a>'; + })); + }; +}]; + + +docsApp.directive.errorDisplay = ['$location', 'errorLinkFilter', function ($location, errorLinkFilter) { var interpolate = function (formatString) { var formatArgs = arguments; return formatString.replace(/\{\d+\}/g, function (match) { @@ -278,7 +312,7 @@ docsApp.directive.errorDisplay = ['$location', function ($location) { for (i = 0; angular.isDefined(search['p'+i]); i++) { formatArgs.push(search['p'+i]); } - element.text(interpolate.apply(null, formatArgs)); + element.html(errorLinkFilter(interpolate.apply(null, formatArgs), '_blank')); } }; }]; @@ -873,3 +907,7 @@ angular.module('docsApp', ['ngResource', 'ngRoute', 'ngCookies', 'ngSanitize', ' factory(docsApp.serviceFactory). directive(docsApp.directive). controller(docsApp.controller); + +angular.forEach(docsApp.filter, function (docsAppFilter, filterName) { + angular.module('docsApp').filter(filterName, docsAppFilter); +}); |
