@@ -9,6 +9,7 @@ gem 'haml' |
||
9 | 9 |
gem 'json' |
10 | 10 |
gem 'rack-cors', :require => 'rack/cors' |
11 | 11 |
gem 'unirest' |
12 |
+gem 'mixpanel-ruby' |
|
12 | 13 |
|
13 | 14 |
group :test, :development do |
14 | 15 |
gem 'pry' |
@@ -14,6 +14,7 @@ GEM |
||
14 | 14 |
kgio (2.7.4) |
15 | 15 |
method_source (0.8.2) |
16 | 16 |
mime-types (2.6.1) |
17 |
+ mixpanel-ruby (2.1.0) |
|
17 | 18 |
netrc (0.10.3) |
18 | 19 |
pry (0.10.1) |
19 | 20 |
coderay (~> 1.1.0) |
@@ -63,6 +64,7 @@ PLATFORMS |
||
63 | 64 |
DEPENDENCIES |
64 | 65 |
haml |
65 | 66 |
json |
67 |
+ mixpanel-ruby |
|
66 | 68 |
pry |
67 | 69 |
rack-cors |
68 | 70 |
rb-readline |
@@ -0,0 +1,18 @@ |
||
1 |
+require 'mixpanel-ruby' |
|
2 |
+ |
|
3 |
+class Analytics |
|
4 |
+ |
|
5 |
+ def self.track(user_id, event_name, url = '') |
|
6 |
+ tracker = Mixpanel::Tracker.new('8f581bbd244b7ee0f4762d322ac617e8') |
|
7 |
+ |
|
8 |
+ # Tracks an event, 'Sent Message', |
|
9 |
+ # with distinct_id user_id |
|
10 |
+ if url != '' |
|
11 |
+ tracker.track(user_id, event_name, { 'lookup_url' => url}) |
|
12 |
+ else |
|
13 |
+ tracker.track(user_id, event_name) |
|
14 |
+ end |
|
15 |
+ |
|
16 |
+ end |
|
17 |
+ |
|
18 |
+end |
@@ -56,7 +56,7 @@ class WhoisParser |
||
56 | 56 |
# Owner |
57 | 57 |
owner_data = whois_lookup.to_s.scan(/Registrant\sName:\s([^\\]+)/).first |
58 | 58 |
if owner_data != nil |
59 |
- owner_data = spliter(owner_data, "\n").downcase.split.map(&:capitalize).join(' ') |
|
59 |
+ owner_data = spliter(owner_data, "\r").downcase.split.map(&:capitalize).join(' ') |
|
60 | 60 |
if owner_data |
61 | 61 |
@parsed_data["owner"] = owner_data |
62 | 62 |
end |
@@ -5,8 +5,10 @@ require 'json' |
||
5 | 5 |
require 'ostruct' |
6 | 6 |
require "sinatra/reloader" if development? |
7 | 7 |
|
8 |
+ |
|
8 | 9 |
require_relative 'json_parser' |
9 | 10 |
require_relative 'unirest_parser' |
11 |
+require_relative 'analytics' |
|
10 | 12 |
|
11 | 13 |
# ruby crimes |
12 | 14 |
class Whois::Record |
@@ -61,46 +63,12 @@ set :views, File.dirname(__FILE__) + '/views' |
||
61 | 63 |
set :public_folder, File.dirname(__FILE__) + '/public' |
62 | 64 |
|
63 | 65 |
get '/' do |
64 |
- #cache_for_day |
|
66 |
+ Analytics.track(request.ip, 'Page View') |
|
65 | 67 |
File.read(File.join('public', 'index.html')) |
66 | 68 |
end |
67 | 69 |
|
68 |
-get '/lookup' do |
|
69 |
- begin |
|
70 |
- cache_for_day |
|
71 |
- @whois = whois_lookup |
|
72 |
- haml :lookup |
|
73 |
- rescue Exception => e |
|
74 |
- @error = e |
|
75 |
- haml :error |
|
76 |
- end |
|
77 |
-end |
|
78 |
- |
|
79 |
-get '/lookup.json' do |
|
80 |
- content_type 'application/json' |
|
81 |
- response["Content-Type"] = "application/json" |
|
82 |
- headers 'Access-Control-Allow-Origin' => '*', |
|
83 |
- 'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST'] |
|
84 |
- begin |
|
85 |
- #cache_for_day |
|
86 |
- parser = WhoisParser.new |
|
87 |
- if whois_lookup.class != Array |
|
88 |
- data = whois_lookup.to_h |
|
89 |
- else |
|
90 |
- if whois_lookup.first.class != Array |
|
91 |
- data = whois_lookup.first.to_h |
|
92 |
- else |
|
93 |
- data = "" |
|
94 |
- end |
|
95 |
- end |
|
96 |
- parser.parse(data, whois_lookup, params[:url], params[:raw], params[:dev]) |
|
97 |
- rescue Exception => e |
|
98 |
- @error = e |
|
99 |
- { :error => @error }.to_json |
|
100 |
- end |
|
101 |
-end |
|
102 |
- |
|
103 |
-get '/:url' do |
|
70 |
+get '/:lookup_url' do |
|
71 |
+ Analytics.track(request.ip, 'Domain Lookup', params[:lookup_url]) |
|
104 | 72 |
content_type 'application/json' |
105 | 73 |
response["Content-Type"] = "application/json" |
106 | 74 |
headers 'Access-Control-Allow-Origin' => '*', |
@@ -118,7 +86,7 @@ get '/:url' do |
||
118 | 86 |
data = "" |
119 | 87 |
end |
120 | 88 |
end |
121 |
- parser.parse(data, whois_lookup, params[:url], params[:raw], params[:dev]) |
|
89 |
+ parser.parse(data, whois_lookup, params[:lookup_url], params[:raw], params[:dev]) |
|
122 | 90 |
rescue Exception => e |
123 | 91 |
@error = e |
124 | 92 |
{ :error => @error }.to_json |
@@ -0,0 +1,39 @@ |
||
1 |
+/* Sticky footer styles |
|
2 |
+-------------------------------------------------- */ |
|
3 |
+html { |
|
4 |
+ position: relative; |
|
5 |
+ min-height: 100%; |
|
6 |
+} |
|
7 |
+body { |
|
8 |
+ /* Margin bottom by footer height */ |
|
9 |
+ margin-bottom: 60px; |
|
10 |
+} |
|
11 |
+.footer { |
|
12 |
+ position: absolute; |
|
13 |
+ bottom: 0; |
|
14 |
+ width: 100%; |
|
15 |
+ /* Set the fixed height of the footer here */ |
|
16 |
+ height: 60px; |
|
17 |
+ background-color: #f5f5f5; |
|
18 |
+} |
|
19 |
+ |
|
20 |
+ |
|
21 |
+/* Custom page CSS |
|
22 |
+-------------------------------------------------- */ |
|
23 |
+/* Not required for template or sticky footer method. */ |
|
24 |
+ |
|
25 |
+body > .container { |
|
26 |
+ padding: 60px 15px 0; |
|
27 |
+} |
|
28 |
+.container .text-muted { |
|
29 |
+ margin: 20px 0; |
|
30 |
+} |
|
31 |
+ |
|
32 |
+.footer > .container { |
|
33 |
+ padding-right: 15px; |
|
34 |
+ padding-left: 15px; |
|
35 |
+} |
|
36 |
+ |
|
37 |
+code { |
|
38 |
+ font-size: 80%; |
|
39 |
+} |
@@ -11,9 +11,6 @@ body { |
||
11 | 11 |
background: #dedede; |
12 | 12 |
} |
13 | 13 |
|
14 |
-p { |
|
15 |
- margin: 0; |
|
16 |
-} |
|
17 | 14 |
|
18 | 15 |
.info { |
19 | 16 |
width: 800px; |
@@ -52,3 +49,20 @@ p.title { |
||
52 | 49 |
float: left; |
53 | 50 |
margin-left: 15px; |
54 | 51 |
} |
52 |
+ |
|
53 |
+h1 { margin-bottom: 40px;} |
|
54 |
+h2 { margin-bottom: 20px; margin-top: 40px} |
|
55 |
+h4 { margin-bottom: 15px; margin-top: 25px} |
|
56 |
+ |
|
57 |
+.markdown-page { |
|
58 |
+ margin-bottom: 70px; |
|
59 |
+} |
|
60 |
+ |
|
61 |
+pre { |
|
62 |
+ padding: 0; |
|
63 |
+} |
|
64 |
+ |
|
65 |
+code { |
|
66 |
+ color: white; |
|
67 |
+ background-color: #2F2F2F; |
|
68 |
+} |
@@ -0,0 +1,44 @@ |
||
1 |
+/* Tomorrow Night Eighties Theme */ |
|
2 |
+/* Original theme - https://github.com/chriskempson/tomorrow-theme */ |
|
3 |
+/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ |
|
4 |
+.tomorrow-comment, pre .comment, pre .title { |
|
5 |
+ color: #999999; |
|
6 |
+} |
|
7 |
+ |
|
8 |
+.tomorrow-red, pre .variable, pre .regexp, pre .ruby .constant, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { |
|
9 |
+ color: #f2777a; |
|
10 |
+} |
|
11 |
+ |
|
12 |
+.tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant, pre .ruby .function .title, pre .ruby .title .keyword, pre .keyword { |
|
13 |
+ color: #D58B49; |
|
14 |
+} |
|
15 |
+ |
|
16 |
+.tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute, pre .attribute, pre .tag, pre .xml .tag .title { |
|
17 |
+ color: #ECC982; |
|
18 |
+} |
|
19 |
+ |
|
20 |
+.tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .xml .cdata { |
|
21 |
+ color: #B4C978; |
|
22 |
+} |
|
23 |
+ |
|
24 |
+.tomorrow-aqua, pre .css .hexcolor { |
|
25 |
+ color: #66cccc; |
|
26 |
+} |
|
27 |
+ |
|
28 |
+.tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .symbol, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { |
|
29 |
+ color: #7AA3BC; |
|
30 |
+} |
|
31 |
+ |
|
32 |
+.tomorrow-purple, pre .javascript .function { |
|
33 |
+ color: #cc99cc; |
|
34 |
+} |
|
35 |
+ |
|
36 |
+pre code { |
|
37 |
+ display: block; |
|
38 |
+ background: #2F2F2F; |
|
39 |
+ color: #cccccc; |
|
40 |
+ font-family: Menlo, Monaco, Consolas, monospace; |
|
41 |
+ line-height: 1.5; |
|
42 |
+ border: 1px solid #ccc; |
|
43 |
+ padding: 10px; |
|
44 |
+} |
@@ -7,73 +7,78 @@ |
||
7 | 7 |
<meta name="viewport" content="width=device-width"> |
8 | 8 |
|
9 | 9 |
<link rel="stylesheet" href="css/bootstrap.min.css" /> |
10 |
+ <link rel="stylesheet" href="css/sticky-footer-navbar.css" /> |
|
10 | 11 |
<link rel="stylesheet" href="css/styles.css"> |
12 |
+ <link href="css//tomorrow-night-eighties.css?body=1" media="all" rel="stylesheet"> |
|
13 |
+ |
|
14 |
+ |
|
15 |
+ |
|
11 | 16 |
|
12 | 17 |
</head> |
13 |
- <body ng-app="domainManagerApp"> |
|
18 |
+ <body ng-app="WhoisAPI"> |
|
14 | 19 |
<!--[if lt IE 7]> |
15 | 20 |
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> |
16 | 21 |
<![endif]--> |
17 | 22 |
|
18 |
- <!-- Add your site or application content here --> |
|
19 |
- <div class="header"> |
|
20 |
- <div class="navbar navbar-default" role="navigation"> |
|
21 |
- <div class="container"> |
|
22 |
- <div class="navbar-header"> |
|
23 |
- |
|
24 |
- <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#js-navbar-collapse"> |
|
25 |
- <span class="sr-only">Toggle navigation</span> |
|
26 |
- <span class="icon-bar"></span> |
|
27 |
- <span class="icon-bar"></span> |
|
28 |
- <span class="icon-bar"></span> |
|
29 |
- </button> |
|
30 |
- |
|
31 |
- <a class="navbar-brand" href="#/">Whois JSON API</a> |
|
32 |
- </div> |
|
23 |
+ <!-- Fixed navbar --> |
|
24 |
+ <nav class="navbar navbar-default navbar-fixed-top"> |
|
25 |
+ <div class="container"> |
|
26 |
+ <div class="navbar-header"> |
|
27 |
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> |
|
28 |
+ <span class="sr-only">Toggle navigation</span> |
|
29 |
+ <span class="icon-bar"></span> |
|
30 |
+ <span class="icon-bar"></span> |
|
31 |
+ <span class="icon-bar"></span> |
|
32 |
+ </button> |
|
33 |
+ <a class="navbar-brand" href="#/">Whois JSON API</a> |
|
33 | 34 |
</div> |
35 |
+ <div id="navbar" class="collapse navbar-collapse" id="js-navbar-collapse" ng-controller="HeaderController"> |
|
36 |
+ <ul class="nav navbar-nav"> |
|
37 |
+ <li ng-class="{ active: isActive('/')}"><a href="#/">Lookup</a></li> |
|
38 |
+ <li ng-class="{ active: isActive('/docs')}"><a href="#/docs">Docs</a></li> |
|
39 |
+ </ul> |
|
40 |
+ </div><!--/.nav-collapse --> |
|
34 | 41 |
</div> |
35 |
- </div> |
|
42 |
+ </nav> |
|
43 |
+ |
|
44 |
+ |
|
36 | 45 |
|
37 | 46 |
<div class="container"> |
38 |
- <div ng-controller="WhoisController"> |
|
39 |
- <form class="form-horizontal" ng-submit="lookup()"> |
|
40 |
- <fieldset class="domain-search centered"> |
|
41 |
- |
|
42 |
- <div class="domain-input"> |
|
43 |
- <div class="input-group input-group-lg"> |
|
44 |
- <span class="input-group-addon" id="basic-addon1">http://whois.j1x.co/</span> |
|
45 |
- <input id="domainTitle" ng-model="url" name="txtTitle" type="text" placeholder="example.com" class="form-control input-md"> |
|
46 |
- </div> |
|
47 |
- </div> |
|
48 |
- <input id="singlebutton" ng-disabled="!url" name="singlebutton" class="btn btn-primary btn-lg domain-btn"type="submit"value="Search"> |
|
49 |
- |
|
50 |
- |
|
51 |
- </fieldset> |
|
52 |
- </form> |
|
53 |
- <div ng-show="showResult"><pre><code>{{domain}}</code></pre></div> |
|
54 |
- </div> |
|
47 |
+ <div ng-view></div> |
|
55 | 48 |
</div> |
56 | 49 |
|
57 |
- <div footer></div> |
|
50 |
+ <footer class="footer"> |
|
51 |
+ <div class="container"> |
|
52 |
+ <p style="text-align: center" class="text-muted">Whois JSON API website created by <a href="http://jamesperet.com">James Peret</a> - © <a href="http://j1x.co">J1X</a> 2015</p> |
|
53 |
+ </div> |
|
54 |
+ </footer> |
|
55 |
+ |
|
56 |
+ |
|
57 |
+ <script src="js/lib/angular.min.js"></script> |
|
58 |
+ <script src="js/lib/angular-route.min.js"></script> |
|
59 |
+ <script src="js/lib/angular-sanitize.min.js"></script> |
|
60 |
+ <script type="text/javascript" src="http://fgnass.github.io/spin.js/spin.min.js"></script> |
|
61 |
+ <script src="js/lib/angular-spinner.js"></script> |
|
62 |
+ <script src="http://pc035860.github.io/angular-highlightjs/angular-highlightjs.min.js"></script> |
|
63 |
+ <script src="js/lib/showdown.min.js"></script> |
|
64 |
+ <script src="js/lib/ng-showdown.js"></script> |
|
65 |
+ <script src="js/lib/jquery.min.js"></script> |
|
66 |
+ <script src="js/lib/bootstrap.min.js"></script> |
|
67 |
+ <script src="js/scripts/app.js"></script> |
|
68 |
+ |
|
58 | 69 |
|
70 |
+ <script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script> |
|
59 | 71 |
|
60 |
- <!-- Google Analytics: change UA-XXXXX-X to be your site's ID |
|
61 | 72 |
<script> |
62 | 73 |
!function(A,n,g,u,l,a,r){A.GoogleAnalyticsObject=l,A[l]=A[l]||function(){ |
63 | 74 |
(A[l].q=A[l].q||[]).push(arguments)},A[l].l=+new Date,a=n.createElement(g), |
64 | 75 |
r=n.getElementsByTagName(g)[0],a.src=u,r.parentNode.insertBefore(a,r) |
65 | 76 |
}(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
66 | 77 |
|
67 |
- ga('create', 'UA-XXXXX-X'); |
|
78 |
+ ga('create', 'UA-63859108-2'); |
|
68 | 79 |
ga('send', 'pageview'); |
69 | 80 |
</script> |
70 |
- --> |
|
71 | 81 |
|
72 | 82 |
|
73 |
- <script src="js/lib/angular.min.js"></script> |
|
74 |
- <script src="js/lib/jquery.min.js"></script> |
|
75 |
- <script src="js/lib/bootstrap.min.js"></script> |
|
76 |
- <script src="js/scripts/app.js"></script> |
|
77 |
- |
|
78 | 83 |
</body> |
79 | 84 |
</html> |
@@ -0,0 +1,15 @@ |
||
1 |
+/* |
|
2 |
+ AngularJS v1.3.15 |
|
3 |
+ (c) 2010-2014 Google, Inc. http://angularjs.org |
|
4 |
+ License: MIT |
|
5 |
+*/ |
|
6 |
+(function(q,d,C){'use strict';function v(r,k,h){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,f,b,c,y){function z(){l&&(h.cancel(l),l=null);m&&(m.$destroy(),m=null);n&&(l=h.leave(n),l.then(function(){l=null}),n=null)}function x(){var b=r.current&&r.current.locals;if(d.isDefined(b&&b.$template)){var b=a.$new(),c=r.current;n=y(b,function(b){h.enter(b,null,n||f).then(function(){!d.isDefined(t)||t&&!a.$eval(t)||k()});z()});m=c.scope=b;m.$emit("$viewContentLoaded"); |
|
7 |
+m.$eval(w)}else z()}var m,n,l,t=b.autoscroll,w=b.onload||"";a.$on("$routeChangeSuccess",x);x()}}}function A(d,k,h){return{restrict:"ECA",priority:-400,link:function(a,f){var b=h.current,c=b.locals;f.html(c.$template);var y=d(f.contents());b.controller&&(c.$scope=a,c=k(b.controller,c),b.controllerAs&&(a[b.controllerAs]=c),f.data("$ngControllerController",c),f.children().data("$ngControllerController",c));y(a)}}}q=d.module("ngRoute",["ng"]).provider("$route",function(){function r(a,f){return d.extend(Object.create(a), |
|
8 |
+f)}function k(a,d){var b=d.caseInsensitiveMatch,c={originalPath:a,regexp:a},h=c.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,d,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});d=d||"";return""+(a?"":d)+"(?:"+(a?d:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");c.regexp=new RegExp("^"+a+"$",b?"i":"");return c}var h={};this.when=function(a,f){var b=d.copy(f);d.isUndefined(b.reloadOnSearch)&&(b.reloadOnSearch=!0); |
|
9 |
+d.isUndefined(b.caseInsensitiveMatch)&&(b.caseInsensitiveMatch=this.caseInsensitiveMatch);h[a]=d.extend(b,a&&k(a,b));if(a){var c="/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";h[c]=d.extend({redirectTo:a},k(c,b))}return this};this.caseInsensitiveMatch=!1;this.otherwise=function(a){"string"===typeof a&&(a={redirectTo:a});this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(a,f,b,c,k,q,x){function m(b){var e=s.current; |
|
10 |
+(v=(p=l())&&e&&p.$$route===e.$$route&&d.equals(p.pathParams,e.pathParams)&&!p.reloadOnSearch&&!w)||!e&&!p||a.$broadcast("$routeChangeStart",p,e).defaultPrevented&&b&&b.preventDefault()}function n(){var u=s.current,e=p;if(v)u.params=e.params,d.copy(u.params,b),a.$broadcast("$routeUpdate",u);else if(e||u)w=!1,(s.current=e)&&e.redirectTo&&(d.isString(e.redirectTo)?f.path(t(e.redirectTo,e.params)).search(e.params).replace():f.url(e.redirectTo(e.pathParams,f.path(),f.search())).replace()),c.when(e).then(function(){if(e){var a= |
|
11 |
+d.extend({},e.resolve),b,g;d.forEach(a,function(b,e){a[e]=d.isString(b)?k.get(b):k.invoke(b,null,null,e)});d.isDefined(b=e.template)?d.isFunction(b)&&(b=b(e.params)):d.isDefined(g=e.templateUrl)&&(d.isFunction(g)&&(g=g(e.params)),g=x.getTrustedResourceUrl(g),d.isDefined(g)&&(e.loadedTemplateUrl=g,b=q(g)));d.isDefined(b)&&(a.$template=b);return c.all(a)}}).then(function(c){e==s.current&&(e&&(e.locals=c,d.copy(e.params,b)),a.$broadcast("$routeChangeSuccess",e,u))},function(b){e==s.current&&a.$broadcast("$routeChangeError", |
|
12 |
+e,u,b)})}function l(){var a,b;d.forEach(h,function(c,h){var g;if(g=!b){var k=f.path();g=c.keys;var m={};if(c.regexp)if(k=c.regexp.exec(k)){for(var l=1,n=k.length;l<n;++l){var p=g[l-1],q=k[l];p&&q&&(m[p.name]=q)}g=m}else g=null;else g=null;g=a=g}g&&(b=r(c,{params:d.extend({},f.search(),a),pathParams:a}),b.$$route=c)});return b||h[null]&&r(h[null],{params:{},pathParams:{}})}function t(a,b){var c=[];d.forEach((a||"").split(":"),function(a,d){if(0===d)c.push(a);else{var f=a.match(/(\w+)(?:[?*])?(.*)/), |
|
13 |
+h=f[1];c.push(b[h]);c.push(f[2]||"");delete b[h]}});return c.join("")}var w=!1,p,v,s={routes:h,reload:function(){w=!0;a.$evalAsync(function(){m();n()})},updateParams:function(a){if(this.current&&this.current.$$route)a=d.extend({},this.current.params,a),f.path(t(this.current.$$route.originalPath,a)),f.search(a);else throw B("norout");}};a.$on("$locationChangeStart",m);a.$on("$locationChangeSuccess",n);return s}]});var B=d.$$minErr("ngRoute");q.provider("$routeParams",function(){this.$get=function(){return{}}}); |
|
14 |
+q.directive("ngView",v);q.directive("ngView",A);v.$inject=["$route","$anchorScroll","$animate"];A.$inject=["$compile","$controller","$route"]})(window,window.angular); |
|
15 |
+//# sourceMappingURL=angular-route.min.js.map |
@@ -0,0 +1,16 @@ |
||
1 |
+/* |
|
2 |
+ AngularJS v1.4.1-build.4042+sha.071be60 |
|
3 |
+ (c) 2010-2015 Google, Inc. http://angularjs.org |
|
4 |
+ License: MIT |
|
5 |
+*/ |
|
6 |
+(function(n,h,p){'use strict';function E(a){var f=[];r(f,h.noop).chars(a);return f.join("")}function g(a,f){var d={},c=a.split(","),b;for(b=0;b<c.length;b++)d[f?h.lowercase(c[b]):c[b]]=!0;return d}function F(a,f){function d(a,b,d,l){b=h.lowercase(b);if(s[b])for(;e.last()&&t[e.last()];)c("",e.last());u[b]&&e.last()==b&&c("",b);(l=v[b]||!!l)||e.push(b);var m={};d.replace(G,function(b,a,f,c,d){m[a]=q(f||c||d||"")});f.start&&f.start(b,m,l)}function c(b,a){var c=0,d;if(a=h.lowercase(a))for(c=e.length- |
|
7 |
+1;0<=c&&e[c]!=a;c--);if(0<=c){for(d=e.length-1;d>=c;d--)f.end&&f.end(e[d]);e.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,k,e=[],m=a,l;for(e.last=function(){return e[e.length-1]};a;){l="";k=!0;if(e.last()&&w[e.last()])a=a.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*"+e.last()+"[^>]*>","i"),function(a,b){b=b.replace(H,"$1").replace(I,"$1");f.chars&&f.chars(q(b));return""}),c("",e.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e", |
|
8 |
+b)===b&&(f.comment&&f.comment(a.substring(4,b)),a=a.substring(b+3),k=!1);else if(x.test(a)){if(b=a.match(x))a=a.replace(b[0],""),k=!1}else if(J.test(a)){if(b=a.match(y))a=a.substring(b[0].length),b[0].replace(y,c),k=!1}else K.test(a)&&((b=a.match(z))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(z,d)),k=!1):(l+="<",a=a.substring(1)));k&&(b=a.indexOf("<"),l+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),f.chars&&f.chars(q(l)))}if(a==m)throw L("badparse",a);m=a}c()}function q(a){if(!a)return"";A.innerHTML= |
|
9 |
+a.replace(/</g,"<");return A.textContent}function B(a){return a.replace(/&/g,"&").replace(M,function(a){var d=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(d-55296)+(a-56320)+65536)+";"}).replace(N,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"<").replace(/>/g,">")}function r(a,f){var d=!1,c=h.bind(a,a.push);return{start:function(a,k,e){a=h.lowercase(a);!d&&w[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(k,function(d,e){var k=h.lowercase(e),g="img"===a&&"src"===k|| |
|
10 |
+"background"===k;!0!==O[k]||!0===D[k]&&!f(d,g)||(c(" "),c(e),c('="'),c(B(d)),c('"'))}),c(e?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(B(a))}}}var L=h.$$minErr("$sanitize"),z=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,y=/^<\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^</,J=/^<\//,H=/\x3c!--(.*?)--\x3e/g,x=/<!DOCTYPE([^>]*?)>/i, |
|
11 |
+I=/<!\[CDATA\[(.*?)]]\x3e/g,M=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,N=/([^\#-~| |!])/g,v=g("area,br,col,hr,img,wbr");n=g("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr");p=g("rp,rt");var u=h.extend({},p,n),s=h.extend({},n,g("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),t=h.extend({},p,g("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")); |
|
12 |
+n=g("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan,use");var w=g("script,style"),C=h.extend({},v,s,t,u,n),D=g("background,cite,href,longdesc,src,usemap,xlink:href");n=g("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,target,title,type,valign,value,vspace,width"); |
|
13 |
+p=g("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan", |
|
14 |
+!0);var O=h.extend({},D,p,n),A=document.createElement("pre");h.module("ngSanitize",[]).provider("$sanitize",function(){this.$get=["$$sanitizeUri",function(a){return function(f){var d=[];F(f,r(d,function(c,b){return!/^unsafe/.test(a(c,b))}));return d.join("")}}]});h.module("ngSanitize").filter("linky",["$sanitize",function(a){var f=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/,d=/^mailto:/;return function(c,b){function k(a){a&&g.push(E(a))}function e(a,c){g.push("<a "); |
|
15 |
+h.isDefined(b)&&g.push('target="',b,'" ');g.push('href="',a.replace(/"/g,"""),'">');k(c);g.push("</a>")}if(!c)return c;for(var m,l=c,g=[],n,p;m=l.match(f);)n=m[0],m[2]||m[4]||(n=(m[3]?"http://":"mailto:")+n),p=m.index,k(l.substr(0,p)),e(n,m[0].replace(d,"")),l=l.substring(p+m[0].length);k(l);return a(g.join(""))}}])})(window,window.angular); |
|
16 |
+//# sourceMappingURL=angular-sanitize.min.js.map |
@@ -0,0 +1,91 @@ |
||
1 |
+/** |
|
2 |
+ * angular-spinner version 0.5.0 |
|
3 |
+ * License: MIT. |
|
4 |
+ * Copyright (C) 2013, 2014, Uri Shaked and contributors. |
|
5 |
+ */ |
|
6 |
+ |
|
7 |
+(function (root) { |
|
8 |
+ 'use strict'; |
|
9 |
+ |
|
10 |
+ function factory(angular, Spinner) { |
|
11 |
+ |
|
12 |
+ angular |
|
13 |
+ .module('angularSpinner', []) |
|
14 |
+ |
|
15 |
+ .factory('usSpinnerService', ['$rootScope', function ($rootScope) { |
|
16 |
+ var config = {}; |
|
17 |
+ |
|
18 |
+ config.spin = function (key) { |
|
19 |
+ $rootScope.$broadcast('us-spinner:spin', key); |
|
20 |
+ }; |
|
21 |
+ |
|
22 |
+ config.stop = function (key) { |
|
23 |
+ $rootScope.$broadcast('us-spinner:stop', key); |
|
24 |
+ }; |
|
25 |
+ |
|
26 |
+ return config; |
|
27 |
+ }]) |
|
28 |
+ |
|
29 |
+ .directive('usSpinner', ['$window', function ($window) { |
|
30 |
+ return { |
|
31 |
+ scope: true, |
|
32 |
+ link: function (scope, element, attr) { |
|
33 |
+ var SpinnerConstructor = Spinner || $window.Spinner; |
|
34 |
+ |
|
35 |
+ scope.spinner = null; |
|
36 |
+ |
|
37 |
+ scope.key = angular.isDefined(attr.spinnerKey) ? attr.spinnerKey : false; |
|
38 |
+ |
|
39 |
+ scope.startActive = angular.isDefined(attr.spinnerStartActive) ? |
|
40 |
+ attr.spinnerStartActive : scope.key ? |
|
41 |
+ false : true; |
|
42 |
+ |
|
43 |
+ scope.spin = function () { |
|
44 |
+ if (scope.spinner) { |
|
45 |
+ scope.spinner.spin(element[0]); |
|
46 |
+ } |
|
47 |
+ }; |
|
48 |
+ |
|
49 |
+ scope.stop = function () { |
|
50 |
+ if (scope.spinner) { |
|
51 |
+ scope.spinner.stop(); |
|
52 |
+ } |
|
53 |
+ }; |
|
54 |
+ |
|
55 |
+ scope.$watch(attr.usSpinner, function (options) { |
|
56 |
+ scope.stop(); |
|
57 |
+ scope.spinner = new SpinnerConstructor(options); |
|
58 |
+ if (!scope.key || scope.startActive) { |
|
59 |
+ scope.spinner.spin(element[0]); |
|
60 |
+ } |
|
61 |
+ }, true); |
|
62 |
+ |
|
63 |
+ scope.$on('us-spinner:spin', function (event, key) { |
|
64 |
+ if (key === scope.key) { |
|
65 |
+ scope.spin(); |
|
66 |
+ } |
|
67 |
+ }); |
|
68 |
+ |
|
69 |
+ scope.$on('us-spinner:stop', function (event, key) { |
|
70 |
+ if (key === scope.key) { |
|
71 |
+ scope.stop(); |
|
72 |
+ } |
|
73 |
+ }); |
|
74 |
+ |
|
75 |
+ scope.$on('$destroy', function () { |
|
76 |
+ scope.stop(); |
|
77 |
+ scope.spinner = null; |
|
78 |
+ }); |
|
79 |
+ } |
|
80 |
+ }; |
|
81 |
+ }]); |
|
82 |
+ } |
|
83 |
+ |
|
84 |
+ if (typeof define === 'function' && define.amd) { |
|
85 |
+ /* AMD module */ |
|
86 |
+ define(['angular', 'spin'], factory); |
|
87 |
+ } else { |
|
88 |
+ /* Browser global */ |
|
89 |
+ factory(root.angular); |
|
90 |
+ } |
|
91 |
+}(window)); |
@@ -0,0 +1,150 @@ |
||
1 |
+// Conditional load for NodeJS |
|
2 |
+if (typeof require !== 'undefined') { |
|
3 |
+ var angular = require('angular'), |
|
4 |
+ showdown = require('showdown'); |
|
5 |
+} |
|
6 |
+ |
|
7 |
+//Check if AngularJs and Showdown is defined and only load ng-Showdown if both are present |
|
8 |
+if (typeof angular !== 'undefined' && typeof showdown !== 'undefined') { |
|
9 |
+ |
|
10 |
+ (function (module, showdown) { |
|
11 |
+ 'use strict'; |
|
12 |
+ |
|
13 |
+ module |
|
14 |
+ .provider('$showdown', provider) |
|
15 |
+ .directive('sdModelToHtml', ['$showdown', '$sanitize', markdownToHtmlDirective]) |
|
16 |
+ .filter('sdStripHtml', stripHtmlFilter); |
|
17 |
+ |
|
18 |
+ /** |
|
19 |
+ * Angular Provider |
|
20 |
+ * Enables configuration of showdown via angular.config and Dependency Injection into controllers, views |
|
21 |
+ * directives, etc... This assures the directives and filters provided by the library itself stay consistent |
|
22 |
+ * with the user configurations. |
|
23 |
+ * If the user wants to use a different configuration in a determined context, he can use the "classic" Showdown |
|
24 |
+ * object instead. |
|
25 |
+ */ |
|
26 |
+ function provider() { |
|
27 |
+ |
|
28 |
+ // Configuration parameters for Showdown |
|
29 |
+ var config = { |
|
30 |
+ extensions: [], |
|
31 |
+ stripHtml: true |
|
32 |
+ }; |
|
33 |
+ |
|
34 |
+ /** |
|
35 |
+ * Sets a configuration option |
|
36 |
+ * |
|
37 |
+ * @param {string} key Config parameter key |
|
38 |
+ * @param {string} value Config parameter value |
|
39 |
+ */ |
|
40 |
+ /* jshint validthis: true */ |
|
41 |
+ this.setOption = function (key, value) { |
|
42 |
+ config[key] = value; |
|
43 |
+ |
|
44 |
+ return this; |
|
45 |
+ }; |
|
46 |
+ |
|
47 |
+ /** |
|
48 |
+ * Gets the value of the configuration parameter specified by key |
|
49 |
+ * |
|
50 |
+ * @param {string} key The config parameter key |
|
51 |
+ * @returns {string|null} Returns the value of the config parameter. (or null if the config parameter is not set) |
|
52 |
+ */ |
|
53 |
+ this.getOption = function (key) { |
|
54 |
+ if (config.hasOwnProperty(key)) { |
|
55 |
+ return config.key; |
|
56 |
+ } else { |
|
57 |
+ return null; |
|
58 |
+ } |
|
59 |
+ }; |
|
60 |
+ |
|
61 |
+ /** |
|
62 |
+ * Loads a Showdown Extension |
|
63 |
+ * |
|
64 |
+ * @param {string} extensionName The name of the extension to load |
|
65 |
+ */ |
|
66 |
+ this.loadExtension = function (extensionName) { |
|
67 |
+ config.extensions.push(extensionName); |
|
68 |
+ |
|
69 |
+ return this; |
|
70 |
+ }; |
|
71 |
+ |
|
72 |
+ function SDObject() { |
|
73 |
+ var converter = new showdown.Converter(config); |
|
74 |
+ |
|
75 |
+ /** |
|
76 |
+ * Converts a markdown text into HTML |
|
77 |
+ * |
|
78 |
+ * @param {string} markdown The markdown string to be converted to HTML |
|
79 |
+ * @returns {string} The converted HTML |
|
80 |
+ */ |
|
81 |
+ this.makeHtml = function (markdown) { |
|
82 |
+ return converter.makeHtml(markdown); |
|
83 |
+ }; |
|
84 |
+ |
|
85 |
+ /** |
|
86 |
+ * Strips a text of it's HTML tags |
|
87 |
+ * |
|
88 |
+ * @param {string} text |
|
89 |
+ * @returns {string} |
|
90 |
+ */ |
|
91 |
+ this.stripHtml = function (text) { |
|
92 |
+ return String(text).replace(/<[^>]+>/gm, ''); |
|
93 |
+ }; |
|
94 |
+ } |
|
95 |
+ |
|
96 |
+ // The object returned by service provider |
|
97 |
+ this.$get = function () { |
|
98 |
+ return new SDObject(); |
|
99 |
+ }; |
|
100 |
+ } |
|
101 |
+ |
|
102 |
+ /** |
|
103 |
+ * AngularJS Directive to Md to HTML transformation |
|
104 |
+ * |
|
105 |
+ * Usage example: |
|
106 |
+ * <div sd-model-to-html="markdownText" ></div> |
|
107 |
+ * |
|
108 |
+ * @param {showdown.Converter} $showdown |
|
109 |
+ * @param $sanitize |
|
110 |
+ * @returns {*} |
|
111 |
+ */ |
|
112 |
+ function markdownToHtmlDirective($showdown, $sanitize) { |
|
113 |
+ |
|
114 |
+ var link = function (scope, element) { |
|
115 |
+ scope.$watch('model', function (newValue) { |
|
116 |
+ var val; |
|
117 |
+ if (typeof newValue === 'string') { |
|
118 |
+ val = $sanitize($showdown.makeHtml(newValue)); |
|
119 |
+ } else { |
|
120 |
+ val = typeof newValue; |
|
121 |
+ } |
|
122 |
+ element.html(val); |
|
123 |
+ }); |
|
124 |
+ }; |
|
125 |
+ |
|
126 |
+ return { |
|
127 |
+ restrict: 'A', |
|
128 |
+ link: link, |
|
129 |
+ scope: { |
|
130 |
+ model: '=sdModelToHtml' |
|
131 |
+ } |
|
132 |
+ }; |
|
133 |
+ } |
|
134 |
+ |
|
135 |
+ /** |
|
136 |
+ * AngularJS Filter to Strip HTML tags from text |
|
137 |
+ * |
|
138 |
+ * @returns {Function} |
|
139 |
+ */ |
|
140 |
+ function stripHtmlFilter() { |
|
141 |
+ return function (text) { |
|
142 |
+ return String(text).replace(/<[^>]+>/gm, ''); |
|
143 |
+ }; |
|
144 |
+ } |
|
145 |
+ |
|
146 |
+ })(angular.module('showdown', ['ngSanitize']), showdown); |
|
147 |
+ |
|
148 |
+} else { |
|
149 |
+ throw new Error('ng-showdown was not loaded because one of its dependencies (AngularJS or Showdown) was not met'); |
|
150 |
+} |
@@ -0,0 +1,4 @@ |
||
1 |
+/*! showdown 07-06-2015 */ |
|
2 |
+ |
|
3 |
+(function(){function a(a,b){"use strict";var d=b?"Error in "+b+" extension->":"Error in unnamed extension",e={valid:!0,error:""};c.helper.isArray(a)||(a=[a]);for(var f=0;f<a.length;++f){var g=d+"sub-extension "+f+": ",h=a[f];if("object"!=typeof h)return e.valid=!1,e.error=g+"must be an object, but "+typeof h+" given",e;if(!c.helper.isString(h.type))return e.valid=!1,e.error=g+'property "type" must be a string, but '+typeof h.type+" given",e;var i=h.type=h.type.toLowerCase();if("language"===i&&(i=h.type="lang"),"html"===i&&(i=h.type="output"),"lang"!==i&&"output"!==i)return e.valid=!1,e.error=g+"type "+i+' is not recognized. Valid values: "lang" or "output"',e;if(h.filter){if("function"!=typeof h.filter)return e.valid=!1,e.error=g+'"filter" must be a function, but '+typeof h.filter+" given",e}else{if(!h.regex)return e.valid=!1,e.error=g+'extensions must define either a "regex" property or a "filter" method',e;if(c.helper.isString(h.regex)&&(h.regex=new RegExp(h.regex,"g")),!h.regex instanceof RegExp)return e.valid=!1,e.error=g+'"regex" property must either be a string or a RegExp object, but '+typeof h.regex+" given",e;if(c.helper.isUndefined(h.replace))return e.valid=!1,e.error=g+'"regex" extensions must implement a replace string or function',e}if(c.helper.isUndefined(h.filter)&&c.helper.isUndefined(h.regex))return e.valid=!1,e.error=g+"output extensions must define a filter property",e}return e}function b(a,b){"use strict";var c=b.charCodeAt(0);return"~E"+c+"E"}var c={},d={},e={},f={omitExtraWLInCodeBlocks:!1,prefixHeaderId:!1},g=JSON.parse(JSON.stringify(f));c.helper={},c.extensions={},c.setOption=function(a,b){"use strict";return g[a]=b,this},c.getOption=function(a){"use strict";return g[a]},c.getOptions=function(){"use strict";return g},c.resetOptions=function(){"use strict";g=JSON.parse(JSON.stringify(f))},c.subParser=function(a,b){"use strict";if(c.helper.isString(a)){if("undefined"==typeof b){if(d.hasOwnProperty(a))return d[a];throw Error("SubParser named "+a+" not registered!")}d[a]=b}},c.extension=function(b,d){"use strict";if(!c.helper.isString(b))throw Error("Extension 'name' must be a string");if(b=c.helper.stdExtName(b),c.helper.isUndefined(d)){if(!e.hasOwnProperty(b))throw Error("Extension named "+b+" is not registered!");return e[b]}"function"==typeof d&&(d=d()),c.helper.isArray(d)||(d=[d]);var f=a(d,b);if(!f.valid)throw Error(f.error);e[b]=d},c.getAllExtensions=function(){"use strict";return e},c.removeExtension=function(a){"use strict";delete e[a]},c.resetExtensions=function(){"use strict";e={}},c.validateExtension=function(b){"use strict";var c=a(b,null);return c.valid?!0:(console.warn(c.error),!1)},c.hasOwnProperty("helper")||(c.helper={}),c.helper.isString=function(a){"use strict";return"string"==typeof a||a instanceof String},c.helper.forEach=function(a,b){"use strict";if("function"==typeof a.forEach)a.forEach(b);else for(var c=0;c<a.length;c++)b(a[c],c,a)},c.helper.isArray=function(a){"use strict";return a.constructor===Array},c.helper.isUndefined=function(a){"use strict";return"undefined"==typeof a},c.helper.stdExtName=function(a){"use strict";return a.replace(/[_-]||\s/g,"").toLowerCase()},c.helper.escapeCharactersCallback=b,c.helper.escapeCharacters=function(a,c,d){"use strict";var e="(["+c.replace(/([\[\]\\])/g,"\\$1")+"])";d&&(e="\\\\"+e);var f=new RegExp(e,"g");return a=a.replace(f,b)},c.helper.isUndefined(console)&&(console={warn:function(a){"use strict";alert(a)},log:function(a){"use strict";alert(a)}}),c.Converter=function(b){"use strict";function f(){b=b||{};for(var a in g)g.hasOwnProperty(a)&&(j[a]=g[a]);if("object"!=typeof b)throw Error("Converter expects the passed parameter to be an object, but "+typeof b+" was passed instead.");for(var d in b)b.hasOwnProperty(d)&&(j[d]=b[d]);j.extensions&&c.helper.forEach(j.extensions,h)}function h(a){if(c.helper.isString(a)){if(a=c.helper.stdExtName(a),c.extensions[a])return console.warn("DEPRECATION WARNING: "+a+" is an old extension that uses a deprecated loading method.Please inform the developer that the extension should be updated!"),void i(c.extensions[a],a);if(c.helper.isUndefined(e[a]))throw Error('Extension "'+a+'" could not be loaded. It was either not found or is not a valid extension.');a=e[a]}if("function"==typeof a&&(a=a()),c.helper.isArray(a)||(a=[a]),c.validateExtension(a))for(var b=0;b<a.length;++b)switch(a[b].type){case"lang":k.push(a[b]);break;case"output":l.push(a[b]);break;default:throw Error("Extension loader error: Type unrecognized!!!")}}function i(b,d){"function"==typeof b&&(b=b(new c.Converter)),c.helper.isArray(b)||(b=[b]);var e=a(b,d);if(!e.valid)throw Error(e.error);for(var f=0;f<b.length;++f)switch(b[f].type){case"lang":k.push(b[f]);break;case"output":l.push(b[f]);break;default:throw Error("Extension loader error: Type unrecognized!!!")}}var j={omitExtraWLInCodeBlocks:!1,prefixHeaderId:!1},k=[],l=[],m=["githubCodeBlocks","hashHTMLBlocks","stripLinkDefinitions","blockGamut","unescapeSpecialChars"];f(),this.makeHtml=function(a){if(!a)return a;var b={gHtmlBlocks:[],gUrls:{},gTitles:{},gListLevel:0,hashLinkCounts:{},langExtensions:k,outputModifiers:l,converter:this};a=a.replace(/~/g,"~T"),a=a.replace(/\$/g,"~D"),a=a.replace(/\r\n/g,"\n"),a=a.replace(/\r/g,"\n"),a="\n\n"+a+"\n\n",a=c.subParser("detab")(a,j,b),a=c.subParser("stripBlankLines")(a,j,b),c.helper.forEach(k,function(d){a=c.subParser("runExtension")(d,a,j,b)});for(var e=0;e<m.length;++e){var f=m[e];a=d[f](a,j,b)}return a=a.replace(/~D/g,"$$"),a=a.replace(/~T/g,"~"),c.helper.forEach(l,function(d){a=c.subParser("runExtension")(d,a,j,b)}),a},this.setOption=function(a,b){j[a]=b},this.getOption=function(a){return j[a]},this.getOptions=function(){return j},this.addExtension=function(a){h(a)},this.useExtension=function(a){h(a)},this.removeExtension=function(a){c.helper.isArray(a)||(a=[a]);for(var b=0;b<a.length;++b){for(var d=a[b],e=0;e<k.length;++e)k[e]===d&&k[e].splice(e,1);for(var f=0;f<l.length;++e)l[f]===d&&l[f].splice(e,1)}},this.getAllExtensions=function(){return{language:k,output:l}}},c.subParser("anchors",function(a,b,d){"use strict";var e=function(a,b,e,f,g,h,i,j){c.helper.isUndefined(j)&&(j=""),a=b;var k=e,l=f.toLowerCase(),m=g,n=j;if(!m)if(l||(l=k.toLowerCase().replace(/ ?\n/g," ")),m="#"+l,c.helper.isUndefined(d.gUrls[l])){if(!(a.search(/\(\s*\)$/m)>-1))return a;m=""}else m=d.gUrls[l],c.helper.isUndefined(d.gTitles[l])||(n=d.gTitles[l]);m=c.helper.escapeCharacters(m,"*_",!1);var o='<a href="'+m+'"';return""!==n&&null!==n&&(n=n.replace(/"/g,"""),n=c.helper.escapeCharacters(n,"*_",!1),o+=' title="'+n+'"'),o+=">"+k+"</a>"};return a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,e),a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,e),a=a.replace(/(\[([^\[\]]+)\])()()()()()/g,e)}),c.subParser("autoLinks",function(a){"use strict";a=a.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'<a href="$1">$1</a>');var b=/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;return a=a.replace(b,function(a,b){var d=c.subParser("unescapeSpecialChars")(b);return c.subParser("encodeEmailAddress")(d)})}),c.subParser("blockGamut",function(a,b,d){"use strict";a=c.subParser("headers")(a,b,d);var e=c.subParser("hashBlock")("<hr />",b,d);return a=a.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,e),a=a.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,e),a=a.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,e),a=c.subParser("lists")(a,b,d),a=c.subParser("codeBlocks")(a,b,d),a=c.subParser("blockQuotes")(a,b,d),a=c.subParser("hashHTMLBlocks")(a,b,d),a=c.subParser("paragraphs")(a,b,d)}),c.subParser("blockQuotes",function(a,b,d){"use strict";return a=a.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(a,e){var f=e;return f=f.replace(/^[ \t]*>[ \t]?/gm,"~0"),f=f.replace(/~0/g,""),f=f.replace(/^[ \t]+$/gm,""),f=c.subParser("blockGamut")(f,b,d),f=f.replace(/(^|\n)/g,"$1 "),f=f.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(a,b){var c=b;return c=c.replace(/^ /gm,"~0"),c=c.replace(/~0/g,"")}),c.subParser("hashBlock")("<blockquote>\n"+f+"\n</blockquote>",b,d)})}),c.subParser("codeBlocks",function(a,b,d){"use strict";a+="~0";var e=/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g;return a=a.replace(e,function(a,e,f){var g=e,h=f,i="\n";return g=c.subParser("outdent")(g),g=c.subParser("encodeCode")(g),g=c.subParser("detab")(g),g=g.replace(/^\n+/g,""),g=g.replace(/\n+$/g,""),b.omitExtraWLInCodeBlocks&&(i=""),g="<pre><code>"+g+i+"</code></pre>",c.subParser("hashBlock")(g,b,d)+h}),a=a.replace(/~0/,"")}),c.subParser("codeSpans",function(a){"use strict";return a=a.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(a,b,d,e){var f=e;return f=f.replace(/^([ \t]*)/g,""),f=f.replace(/[ \t]*$/g,""),f=c.subParser("encodeCode")(f),b+"<code>"+f+"</code>"})}),c.subParser("detab",function(a){"use strict";return a=a.replace(/\t(?=\t)/g," "),a=a.replace(/\t/g,"~A~B"),a=a.replace(/~B(.+?)~A/g,function(a,b){for(var c=b,d=4-c.length%4,e=0;d>e;e++)c+=" ";return c}),a=a.replace(/~A/g," "),a=a.replace(/~B/g,"")}),c.subParser("encodeAmpsAndAngles",function(a){"use strict";return a=a.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"),a=a.replace(/<(?![a-z\/?\$!])/gi,"<")}),c.subParser("encodeBackslashEscapes",function(a){"use strict";return a=a.replace(/\\(\\)/g,c.helper.escapeCharactersCallback),a=a.replace(/\\([`*_{}\[\]()>#+-.!])/g,c.helper.escapeCharactersCallback)}),c.subParser("encodeCode",function(a){"use strict";return a=a.replace(/&/g,"&"),a=a.replace(/</g,"<"),a=a.replace(/>/g,">"),a=c.helper.escapeCharacters(a,"*_{}[]\\",!1)}),c.subParser("encodeEmailAddress",function(a){"use strict";var b=[function(a){return"&#"+a.charCodeAt(0)+";"},function(a){return"&#x"+a.charCodeAt(0).toString(16)+";"},function(a){return a}];return a="mailto:"+a,a=a.replace(/./g,function(a){if("@"===a)a=b[Math.floor(2*Math.random())](a);else if(":"!==a){var c=Math.random();a=c>.9?b[2](a):c>.45?b[1](a):b[0](a)}return a}),a='<a href="'+a+'">'+a+"</a>",a=a.replace(/">.+:/g,'">')}),c.subParser("escapeSpecialCharsWithinTagAttributes",function(a){"use strict";var b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;return a=a.replace(b,function(a){var b=a.replace(/(.)<\/?code>(?=.)/g,"$1`");return b=c.helper.escapeCharacters(b,"\\`*_",!1)})}),c.subParser("githubCodeBlocks",function(a,b,d){"use strict";return a+="~0",a=a.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,function(a,e,f){var g=e,h=f,i="\n";return b.omitExtraWLInCodeBlocks&&(i=""),h=c.subParser("encodeCode")(h),h=c.subParser("detab")(h),h=h.replace(/^\n+/g,""),h=h.replace(/\n+$/g,""),h="<pre><code"+(g?' class="'+g+'"':"")+">"+h+i+"</code></pre>",c.subParser("hashBlock")(h,b,d)}),a=a.replace(/~0/,"")}),c.subParser("hashBlock",function(a,b,c){"use strict";return a=a.replace(/(^\n+|\n+$)/g,""),"\n\n~K"+(c.gHtmlBlocks.push(a)-1)+"K\n\n"}),c.subParser("hashElement",function(a,b,c){"use strict";return function(a,b){var d=b;return d=d.replace(/\n\n/g,"\n"),d=d.replace(/^\n/,""),d=d.replace(/\n+$/g,""),d="\n\n~K"+(c.gHtmlBlocks.push(d)-1)+"K\n\n"}}),c.subParser("hashHTMLBlocks",function(a,b,d){"use strict";return a=a.replace(/\n/g,"\n\n"),a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,c.subParser("hashElement")(a,b,d)),a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside|address|audio|canvas|figure|hgroup|output|video)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,c.subParser("hashElement")(a,b,d)),a=a.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,c.subParser("hashElement")(a,b,d)),a=a.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,c.subParser("hashElement")(a,b,d)),a=a.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,c.subParser("hashElement")(a,b,d)),a=a.replace(/\n\n/g,"\n")}),c.subParser("headers",function(a,b,d){"use strict";function e(a){var b,e=a.replace(/[^\w]/g,"").toLowerCase();return d.hashLinkCounts[e]?b=e+"-"+d.hashLinkCounts[e]++:(b=e,d.hashLinkCounts[e]=1),f===!0&&(f="section"),c.helper.isString(f)?f+b:b}var f=b.prefixHeaderId;return a=a.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(a,f){var g=c.subParser("spanGamut")(f,b,d),h='<h1 id="'+e(f)+'">'+g+"</h1>";return c.subParser("hashBlock")(h,b,d)}),a=a.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(a,f){var g=c.subParser("spanGamut")(f,b,d),h='<h2 id="'+e(f)+'">'+g+"</h2>";return c.subParser("hashBlock")(h,b,d)}),a=a.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(a,f,g){var h=c.subParser("spanGamut")(g,b,d),i="<h"+f.length+' id="'+e(g)+'">'+h+"</h"+f.length+">";return c.subParser("hashBlock")(i,b,d)})}),c.subParser("images",function(a,b,d){"use strict";var e=function(a,b,e,f,g,h,i,j){a=b;var k=e,l=f.toLowerCase(),m=g,n=j,o=d.gUrls,p=d.gTitles;if(n||(n=""),""===m||null===m){if((""===l||null===l)&&(l=k.toLowerCase().replace(/ ?\n/g," ")),m="#"+l,"undefined"==typeof o[l])return a;m=o[l],"undefined"!=typeof p[l]&&(n=p[l])}k=k.replace(/"/g,"""),m=c.helper.escapeCharacters(m,"*_",!1);var q='<img src="'+m+'" alt="'+k+'"';return n=n.replace(/"/g,"""),n=c.helper.escapeCharacters(n,"*_",!1),q+=' title="'+n+'"',q+=" />"};return a=a.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,e),a=a.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,e)}),c.subParser("italicsAndBold",function(a){"use strict";return a=a.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"<strong>$2</strong>"),a=a.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>")}),c.subParser("lists",function(a,b,d){"use strict";var e=function(a){return d.gListLevel++,a=a.replace(/\n{2,}$/,"\n"),a+="~0",a=a.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(a,e,f,g,h){var i=c.subParser("outdent")(h,b,d);return e||i.search(/\n{2,}/)>-1?i=c.subParser("blockGamut")(i,b,d):(i=c.subParser("lists")(i,b,d),i=i.replace(/\n$/,""),i=c.subParser("spanGamut")(i,b,d)),"<li>"+i+"</li>\n"}),a=a.replace(/~0/g,""),d.gListLevel--,a};a+="~0";var f=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;return d.gListLevel?a=a.replace(f,function(a,b,c){var d=b,f=c.search(/[*+-]/g)>-1?"ul":"ol";d=d.replace(/\n{2,}/g,"\n\n\n");var g=e(d);return g=g.replace(/\s+$/,""),g="<"+f+">"+g+"</"+f+">\n"}):(f=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g,a=a.replace(f,function(a,b,c,d){var f=c.replace(/\n{2,}/g,"\n\n\n"),g=d.search(/[*+-]/g)>-1?"ul":"ol",h=e(f);return b+"<"+g+">\n"+h+"</"+g+">\n"})),a=a.replace(/~0/,"")}),c.subParser("outdent",function(a){"use strict";return a=a.replace(/^(\t|[ ]{1,4})/gm,"~0"),a=a.replace(/~0/g,"")}),c.subParser("paragraphs",function(a,b,d){"use strict";a=a.replace(/^\n+/g,""),a=a.replace(/\n+$/g,"");for(var e=a.split(/\n{2,}/g),f=[],g=e.length,h=0;g>h;h++){var i=e[h];i.search(/~K(\d+)K/g)>=0?f.push(i):i.search(/\S/)>=0&&(i=c.subParser("spanGamut")(i,b,d),i=i.replace(/^([ \t]*)/g,"<p>"),i+="</p>",f.push(i))}for(g=f.length,h=0;g>h;h++)for(;f[h].search(/~K(\d+)K/)>=0;){var j=d.gHtmlBlocks[RegExp.$1];j=j.replace(/\$/g,"$$$$"),f[h]=f[h].replace(/~K\d+K/,j)}return f.join("\n\n")}),c.subParser("runExtension",function(a,b,c,d){"use strict";if(a.filter)b=a.filter(b,d.converter,c);else if(a.regex){var e=a.regex;!e instanceof RegExp&&(e=new RegExp(e,"g")),b=b.replace(e,a.replace)}return b}),c.subParser("spanGamut",function(a,b,d){"use strict";return a=c.subParser("codeSpans")(a,b,d),a=c.subParser("escapeSpecialCharsWithinTagAttributes")(a,b,d),a=c.subParser("encodeBackslashEscapes")(a,b,d),a=c.subParser("images")(a,b,d),a=c.subParser("anchors")(a,b,d),a=c.subParser("autoLinks")(a,b,d),a=c.subParser("encodeAmpsAndAngles")(a,b,d),a=c.subParser("italicsAndBold")(a,b,d),a=a.replace(/ +\n/g," <br />\n")}),c.subParser("stripBlankLines",function(a){"use strict";return a.replace(/^[ \t]+$/gm,"")}),c.subParser("stripLinkDefinitions",function(a,b,d){"use strict";var e=/^[ ]{0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm;return a+="~0",a=a.replace(e,function(a,b,e,f,g){return b=b.toLowerCase(),d.gUrls[b]=c.subParser("encodeAmpsAndAngles")(e),f?f+g:(g&&(d.gTitles[b]=g.replace(/"/g,""")),"")}),a=a.replace(/~0/,"")}),c.subParser("unescapeSpecialChars",function(a){"use strict";return a=a.replace(/~E(\d+)E/g,function(a,b){var c=parseInt(b);return String.fromCharCode(c)})});var h=this;"undefined"!=typeof module&&module.exports?module.exports=c:"function"==typeof define&&define.amd?define("showdown",function(){"use strict";return c}):h.showdown=c}).call(this); |
|
4 |
+//# sourceMappingURL=showdown.min.js.map |
@@ -9,30 +9,100 @@ |
||
9 | 9 |
* Main module of the application. |
10 | 10 |
*/ |
11 | 11 |
angular |
12 |
- .module('domainManagerApp', []) |
|
12 |
+ .module('WhoisAPI', ['ngRoute', 'ngSanitize', 'showdown', 'hljs', 'angularSpinner']) |
|
13 |
+ |
|
14 |
+ .config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) { |
|
15 |
+ // Configs |
|
16 |
+ //Enable cross domain calls |
|
17 |
+ $httpProvider.defaults.useXDomain = true; |
|
18 |
+ //Remove the header used to identify ajax call that would prevent CORS from working |
|
19 |
+ delete $httpProvider.defaults.headers.common['X-Requested-With']; |
|
20 |
+ // Routes |
|
21 |
+ $routeProvider |
|
22 |
+ .when('/', { |
|
23 |
+ templateUrl: 'views/lookup.html', |
|
24 |
+ controller: 'WhoisController' |
|
25 |
+ }) |
|
26 |
+ .when('/docs', { |
|
27 |
+ templateUrl: 'views/docs.html', |
|
28 |
+ controller: 'DocsController' |
|
29 |
+ }) |
|
30 |
+ .otherwise({ |
|
31 |
+ redirectTo: '/' |
|
32 |
+ }); |
|
33 |
+ }]) |
|
13 | 34 |
|
14 |
- .controller('WhoisController',['$scope', '$http', function ($scope, $http) { |
|
15 | 35 |
|
16 |
- $scope.domain = "" |
|
17 |
- $scope.showResult = false |
|
36 |
+ .controller('HeaderController', ['$scope', '$location', function ($scope, $location) { |
|
37 |
+ $scope.isActive = function (viewLocation) { |
|
38 |
+ return viewLocation === $location.path(); |
|
39 |
+ }; |
|
18 | 40 |
|
41 |
+ }]) |
|
19 | 42 |
|
43 |
+ .controller('WhoisController',['$scope', '$rootScope', 'CurrentLookup', 'usSpinnerService', function ($scope, $rootScope, CurrentLookup, usSpinnerService) { |
|
44 |
+ if(CurrentLookup.get() == "") { |
|
45 |
+ $scope.domain = ""; |
|
46 |
+ $scope.showResult = false; |
|
47 |
+ } else { |
|
48 |
+ $scope.domain = JSON.stringify(CurrentLookup.get(), null, 4); |
|
49 |
+ $scope.showResult = true; |
|
50 |
+ $scope.url = CurrentLookup.getUrl(); |
|
51 |
+ } |
|
20 | 52 |
$scope.lookup = function(){ |
53 |
+ usSpinnerService.spin('spinner-1'); |
|
54 |
+ CurrentLookup.domainLookup($scope.url) |
|
55 |
+ } |
|
56 |
+ $rootScope.$on('lookup:finished', function() { |
|
57 |
+ if(!$scope.$$phase) { |
|
58 |
+ $scope.$apply(function(){ |
|
59 |
+ $scope.domain = JSON.stringify(CurrentLookup.get(), null, 4); |
|
60 |
+ $scope.showResult = true |
|
61 |
+ }); |
|
62 |
+ } else { |
|
63 |
+ $scope.domain = JSON.stringify(CurrentLookup.get(), null, 4); |
|
64 |
+ $scope.showResult = true |
|
65 |
+ } |
|
66 |
+ usSpinnerService.stop('spinner-1'); |
|
67 |
+ }); |
|
68 |
+ |
|
69 |
+ }]) |
|
70 |
+ |
|
71 |
+ .controller('DocsController', ['$scope', '$window', function ($scope, $window) { |
|
72 |
+ |
|
73 |
+ }]) |
|
74 |
+ |
|
75 |
+ .service('CurrentLookup', [ '$rootScope', '$http', function($rootScope, $http) { |
|
76 |
+ var domain = ""; |
|
77 |
+ var lastUrl = "" |
|
78 |
+ this.domainLookup = function(url){ |
|
79 |
+ console.log("Starting Domain Lookup...") |
|
21 | 80 |
$http({ |
22 | 81 |
method: 'GET', |
23 |
- url: 'http://whois.j1x.co/' + $scope.url |
|
82 |
+ url: 'http://whois.j1x.co/' + url |
|
24 | 83 |
}).success(function(data) { |
25 | 84 |
console.log("Domain Lookup Successfull") |
26 | 85 |
console.log(data) |
27 |
- if(!$scope.$$phase) { |
|
28 |
- $scope.$apply(function(){ |
|
29 |
- $scope.domain = JSON.stringify(data, null, 4); |
|
30 |
- $scope.showResult = true |
|
31 |
- }); |
|
32 |
- } else { |
|
33 |
- $scope.domain = JSON.stringify(data, null, 4); |
|
34 |
- $scope.showResult = true |
|
35 |
- } |
|
86 |
+ domain = data; |
|
87 |
+ lastUrl = url |
|
88 |
+ $rootScope.$broadcast('lookup:finished'); |
|
36 | 89 |
}); |
37 | 90 |
} |
91 |
+ this.get = function() { |
|
92 |
+ return domain; |
|
93 |
+ } |
|
94 |
+ this.getUrl = function() { |
|
95 |
+ return lastUrl; |
|
96 |
+ } |
|
97 |
+ |
|
98 |
+ }]) |
|
99 |
+ |
|
100 |
+ .directive('markdown', ['$showdown', function ($showdown) { |
|
101 |
+ return { |
|
102 |
+ restrict: 'A', |
|
103 |
+ link: function (scope, element, attrs) { |
|
104 |
+ var htmlText = $showdown.makeHtml(element.text()); |
|
105 |
+ element.html(htmlText); |
|
106 |
+ } |
|
107 |
+ }; |
|
38 | 108 |
}]) |
@@ -0,0 +1,77 @@ |
||
1 |
+<h1>Introduction</h1> |
|
2 |
+ |
|
3 |
+<p>A simplified <b>Whoislookup API</b> with a <b>JSON</b> response. The API returns less information, but with better accuracy than other whois lookup services.</p> |
|
4 |
+ |
|
5 |
+<p>Created by <a href="http://jamesperet.com">James Peret</a>, based on the <a href="https://github.com/okor/whoiz">Whoiz</a> application by <a href="http://jasonormand.com/2012/06/10/a-free-whois-api/">Jason Ormand</a> and using the <a href="http://whoisrb.org/">Ruby Whois</a> gem. |
|
6 |
+ |
|
7 |
+<h2>Accessing the API</h2> |
|
8 |
+ |
|
9 |
+<p>Provide a <b>URL</b> for the <i>API</i> and get a nicely formatted <i>JSON</i> response with the domain information. You can query information in many diferent ways like directly thru the browser, with curl on the command line or with javascript. Here are some examples:</p> |
|
10 |
+ |
|
11 |
+<h4>Browser</h4> |
|
12 |
+<div hljs>http://whois.j1x.co/jamesperet.com</div> |
|
13 |
+ |
|
14 |
+<h4>curl</h4> |
|
15 |
+ |
|
16 |
+<div hljs>curl http://whois.j1x.co/jamesperet.com</div> |
|
17 |
+ |
|
18 |
+<h4>Angular JS Directive</h4> |
|
19 |
+ |
|
20 |
+<div hljs> |
|
21 |
+angular.module('ExampleApp', []) |
|
22 |
+ .service('DomainLookup', [ '$http', function($http) { |
|
23 |
+ domain = "" |
|
24 |
+ this.domainLookup = function(url){ |
|
25 |
+ $http({ |
|
26 |
+ method: 'GET', |
|
27 |
+ url: 'http://whois.j1x.co/' + url |
|
28 |
+ }).success(function(data) { |
|
29 |
+ console.log("Domain Lookup Successfull") |
|
30 |
+ console.log(data) |
|
31 |
+ domain = data; |
|
32 |
+ return domain; |
|
33 |
+ }); |
|
34 |
+ } |
|
35 |
+ this.get = function() { |
|
36 |
+ return domain; |
|
37 |
+ } |
|
38 |
+ }]) |
|
39 |
+</div> |
|
40 |
+ |
|
41 |
+<h2>Query Options</h2> |
|
42 |
+ |
|
43 |
+<p>This are the options for querying the API:</p> |
|
44 |
+<ul> |
|
45 |
+<li> <code>url</code> - The domain url that will be queried. Omit the <code>http://www.</code>.</li> |
|
46 |
+<li> <code>&raw=true</code> - the <i>JSON</i> response will include a <i>raw</i> version of the data received by the <b>registrar</b></li> |
|
47 |
+<li> <code>&dev=true</code> - Only basic information and the *raw* version will be included in the *JSON* response. No parsing will be done with the data. This is useful for <b>debugging</b>b>.</li> |
|
48 |
+</ul> |
|
49 |
+ |
|
50 |
+<p>Example:</p> |
|
51 |
+ |
|
52 |
+<div hljs source="'http://whois.j1x.co/google.com&raw=true'"></div> |
|
53 |
+ |
|
54 |
+ |
|
55 |
+<h2>Example Domain Lookup response</h2> |
|
56 |
+ |
|
57 |
+<div hljs> |
|
58 |
+{ |
|
59 |
+ "domain": "jamesperet.com", |
|
60 |
+ "owner": "James Peret", |
|
61 |
+ "registrar": "eNom Inc.", |
|
62 |
+ "expires_on": "2016-06-07T16:01:00.00Z", |
|
63 |
+ "update_on": "2015-05-13 00:00:00 -0300", |
|
64 |
+ "registered?": true, |
|
65 |
+ "available?": false |
|
66 |
+} |
|
67 |
+</div> |
|
68 |
+ |
|
69 |
+<h2>Domain Support</h2> |
|
70 |
+ |
|
71 |
+<p>For now the supported domains are: <code>.com</code>, <code>.net</code>, <code>.com.br</code> and <code>.network</code>. Support for more domains will come in the future.</p> |
|
72 |
+ |
|
73 |
+<p>The queries for <code>.com.br</code> domains usually come with limited information because of the registrar's API call allowance.</p> |
|
74 |
+ |
|
75 |
+<p>There is also a bug where some <code>.com</code> domains return an error (ex: google.com).</p> |
|
76 |
+ |
|
77 |
+<div style="margin-bottom: 70px;"></div> |
@@ -0,0 +1,16 @@ |
||
1 |
+<form class="form-horizontal" ng-submit="lookup()"> |
|
2 |
+ <fieldset class="domain-search centered"> |
|
3 |
+ |
|
4 |
+ <div class="domain-input"> |
|
5 |
+ <div class="input-group input-group-lg"> |
|
6 |
+ <span class="input-group-addon" id="basic-addon1">http://whois.j1x.co/</span> |
|
7 |
+ <input id="domainTitle" ng-model="url" name="txtTitle" type="text" placeholder="example.com" class="form-control input-md"> |
|
8 |
+ </div> |
|
9 |
+ </div> |
|
10 |
+ <input id="singlebutton" ng-disabled="!url" name="singlebutton" class="btn btn-primary btn-lg domain-btn"type="submit"value="Search"> |
|
11 |
+ |
|
12 |
+ |
|
13 |
+ </fieldset> |
|
14 |
+</form> |
|
15 |
+<span us-spinner="{radius:30, width:8, length: 16}" spinner-key="spinner-1"></span> |
|
16 |
+<div ng-show="showResult"><div hljs source="domain"></div></div> |