Speedometer: ensure all TodoMVC tests use the complete latest CSS
[WebKit-https.git] / PerformanceTests / Speedometer / resources / todomvc / vanilla-examples / es2015 / node_modules / todomvc-common / base.js
1 /* global _ */
2 (function () {
3     'use strict';
4
5     /* jshint ignore:start */
6     // Underscore's Template Module
7     // Courtesy of underscorejs.org
8     var _ = (function (_) {
9         _.defaults = function (object) {
10             if (!object) {
11                 return object;
12             }
13             for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
14                 var iterable = arguments[argsIndex];
15                 if (iterable) {
16                     for (var key in iterable) {
17                         if (object[key] == null) {
18                             object[key] = iterable[key];
19                         }
20                     }
21                 }
22             }
23             return object;
24         };
25
26         // By default, Underscore uses ERB-style template delimiters, change the
27         // following template settings to use alternative delimiters.
28         _.templateSettings = {
29             evaluate    : /<%([\s\S]+?)%>/g,
30             interpolate : /<%=([\s\S]+?)%>/g,
31             escape      : /<%-([\s\S]+?)%>/g
32         };
33
34         // When customizing `templateSettings`, if you don't want to define an
35         // interpolation, evaluation or escaping regex, we need one that is
36         // guaranteed not to match.
37         var noMatch = /(.)^/;
38
39         // Certain characters need to be escaped so that they can be put into a
40         // string literal.
41         var escapes = {
42             "'":      "'",
43             '\\':     '\\',
44             '\r':     'r',
45             '\n':     'n',
46             '\t':     't',
47             '\u2028': 'u2028',
48             '\u2029': 'u2029'
49         };
50
51         var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
52
53         // JavaScript micro-templating, similar to John Resig's implementation.
54         // Underscore templating handles arbitrary delimiters, preserves whitespace,
55         // and correctly escapes quotes within interpolated code.
56         _.template = function(text, data, settings) {
57             var render;
58             settings = _.defaults({}, settings, _.templateSettings);
59
60             // Combine delimiters into one regular expression via alternation.
61             var matcher = new RegExp([
62                 (settings.escape || noMatch).source,
63                 (settings.interpolate || noMatch).source,
64                 (settings.evaluate || noMatch).source
65             ].join('|') + '|$', 'g');
66
67             // Compile the template source, escaping string literals appropriately.
68             var index = 0;
69             var source = "__p+='";
70             text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
71                 source += text.slice(index, offset)
72                     .replace(escaper, function(match) { return '\\' + escapes[match]; });
73
74                 if (escape) {
75                     source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
76                 }
77                 if (interpolate) {
78                     source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
79                 }
80                 if (evaluate) {
81                     source += "';\n" + evaluate + "\n__p+='";
82                 }
83                 index = offset + match.length;
84                 return match;
85             });
86             source += "';\n";
87
88             // If a variable is not specified, place data values in local scope.
89             if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
90
91             source = "var __t,__p='',__j=Array.prototype.join," +
92                 "print=function(){__p+=__j.call(arguments,'');};\n" +
93                 source + "return __p;\n";
94
95             try {
96                 render = new Function(settings.variable || 'obj', '_', source);
97             } catch (e) {
98                 e.source = source;
99                 throw e;
100             }
101
102             if (data) return render(data, _);
103             var template = function(data) {
104                 return render.call(this, data, _);
105             };
106
107             // Provide the compiled function source as a convenience for precompilation.
108             template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
109
110             return template;
111         };
112
113         return _;
114     })({});
115
116     if (location.hostname === 'todomvc.com') {
117         (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
118         (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
119         m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
120         })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
121         ga('create', 'UA-31081062-1', 'auto');
122         ga('send', 'pageview');
123     }
124     /* jshint ignore:end */
125
126     function redirect() {
127         if (location.hostname === 'tastejs.github.io') {
128             location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
129         }
130     }
131
132     function findRoot() {
133         var base = location.href.indexOf('examples/');
134         return location.href.substr(0, base);
135     }
136
137     function getFile(file, callback) {
138         if (!location.host) {
139             return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
140         }
141
142         var xhr = new XMLHttpRequest();
143
144         xhr.open('GET', findRoot() + file, true);
145         xhr.send();
146
147         xhr.onload = function () {
148             if (xhr.status === 200 && callback) {
149                 callback(xhr.responseText);
150             }
151         };
152     }
153
154     function Learn(learnJSON, config) {
155         if (!(this instanceof Learn)) {
156             return new Learn(learnJSON, config);
157         }
158
159         var template, framework;
160
161         if (typeof learnJSON !== 'object') {
162             try {
163                 learnJSON = JSON.parse(learnJSON);
164             } catch (e) {
165                 return;
166             }
167         }
168
169         if (config) {
170             template = config.template;
171             framework = config.framework;
172         }
173
174         if (!template && learnJSON.templates) {
175             template = learnJSON.templates.todomvc;
176         }
177
178         if (!framework && document.querySelector('[data-framework]')) {
179             framework = document.querySelector('[data-framework]').dataset.framework;
180         }
181
182         this.template = template;
183
184         if (learnJSON.backend) {
185             this.frameworkJSON = learnJSON.backend;
186             this.frameworkJSON.issueLabel = framework;
187             this.append({
188                 backend: true
189             });
190         } else if (learnJSON[framework]) {
191             this.frameworkJSON = learnJSON[framework];
192             this.frameworkJSON.issueLabel = framework;
193             this.append();
194         }
195
196         this.fetchIssueCount();
197     }
198
199     Learn.prototype.append = function (opts) {
200         var aside = document.createElement('aside');
201         aside.innerHTML = _.template(this.template, this.frameworkJSON);
202         aside.className = 'learn';
203
204         if (opts && opts.backend) {
205             // Remove demo link
206             var sourceLinks = aside.querySelector('.source-links');
207             var heading = sourceLinks.firstElementChild;
208             var sourceLink = sourceLinks.lastElementChild;
209             // Correct link path
210             var href = sourceLink.getAttribute('href');
211             sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http')));
212             sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML;
213         } else {
214             // Localize demo links
215             var demoLinks = aside.querySelectorAll('.demo-link');
216             Array.prototype.forEach.call(demoLinks, function (demoLink) {
217                 if (demoLink.getAttribute('href').substr(0, 4) !== 'http') {
218                     demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href'));
219                 }
220             });
221         }
222
223         document.body.className = (document.body.className + ' learn-bar').trim();
224         document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
225     };
226
227     Learn.prototype.fetchIssueCount = function () {
228         var issueLink = document.getElementById('issue-count-link');
229         if (issueLink) {
230             var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos');
231             var xhr = new XMLHttpRequest();
232             xhr.open('GET', url, true);
233             xhr.onload = function (e) {
234                 var parsedResponse = JSON.parse(e.target.responseText);
235                 if (parsedResponse instanceof Array) {
236                     var count = parsedResponse.length;
237                     if (count !== 0) {
238                         issueLink.innerHTML = 'This app has ' + count + ' open issues';
239                         document.getElementById('issue-count').style.display = 'inline';
240                     }
241                 }
242             };
243             xhr.send();
244         }
245     };
246
247     redirect();
248     getFile('learn.json', Learn);
249 })();