]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/util/gh-pages/script.js
Rollup merge of #103430 - cjgillot:receiver-attrs, r=petrochenkov
[rust.git] / src / tools / clippy / util / gh-pages / script.js
1 (function () {
2     var md = window.markdownit({
3         html: true,
4         linkify: true,
5         typographer: true,
6         highlight: function (str, lang) {
7             if (lang && hljs.getLanguage(lang)) {
8                 try {
9                     return '<pre class="hljs"><code>' +
10                         hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
11                         '</code></pre>';
12                 } catch (__) {}
13             }
14
15             return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
16         }
17     });
18
19     function scrollToLint(lintId) {
20         var target = document.getElementById(lintId);
21         if (!target) {
22             return;
23         }
24         target.scrollIntoView();
25     }
26
27     function scrollToLintByURL($scope) {
28         var removeListener = $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
29             scrollToLint(window.location.hash.slice(1));
30             removeListener();
31         });
32     }
33
34     function selectGroup($scope, selectedGroup) {
35         var groups = $scope.groups;
36         for (var group in groups) {
37             if (groups.hasOwnProperty(group)) {
38                 if (group === selectedGroup) {
39                     groups[group] = true;
40                 } else {
41                     groups[group] = false;
42                 }
43             }
44         }
45     }
46
47     angular.module("clippy", [])
48         .filter('markdown', function ($sce) {
49             return function (text) {
50                 return $sce.trustAsHtml(
51                     md.render(text || '')
52                         // Oh deer, what a hack :O
53                         .replace('<table', '<table class="table"')
54                 );
55             };
56         })
57         .directive('themeDropdown', function ($document) {
58             return {
59                 restrict: 'A',
60                 link: function ($scope, $element, $attr) {
61                     $element.bind('click', function () {
62                         $element.toggleClass('open');
63                         $element.addClass('open-recent');
64                     });
65
66                     $document.bind('click', function () {
67                         if (!$element.hasClass('open-recent')) {
68                             $element.removeClass('open');
69                         }
70                         $element.removeClass('open-recent');
71                     })
72                 }
73             }
74         })
75         .directive('filterDropdown', function ($document) {
76             return {
77                 restrict: 'A',
78                 link: function ($scope, $element, $attr) {
79                     $element.bind('click', function (event) {
80                         if (event.target.closest('button')) {
81                             $element.toggleClass('open');
82                         } else {
83                             $element.addClass('open');
84                         }
85                         $element.addClass('open-recent');
86                     });
87
88                     $document.bind('click', function () {
89                         if (!$element.hasClass('open-recent')) {
90                             $element.removeClass('open');
91                         }
92                         $element.removeClass('open-recent');
93                     })
94                 }
95             }
96         })
97         .directive('onFinishRender', function ($timeout) {
98             return {
99                 restrict: 'A',
100                 link: function (scope, element, attr) {
101                     if (scope.$last === true) {
102                         $timeout(function () {
103                             scope.$emit(attr.onFinishRender);
104                         });
105                     }
106                 }
107             };
108         })
109         .controller("lintList", function ($scope, $http, $timeout) {
110             // Level filter
111             var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true};
112             $scope.levels = LEVEL_FILTERS_DEFAULT;
113             $scope.byLevels = function (lint) {
114                 return $scope.levels[lint.level];
115             };
116
117             const GROUPS_FILTER_DEFAULT = {
118                 cargo: true,
119                 complexity: true,
120                 correctness: true,
121                 deprecated: false,
122                 nursery: true,
123                 pedantic: true,
124                 perf: true,
125                 restriction: true,
126                 style: true,
127                 suspicious: true,
128             }
129
130             $scope.groups = {
131                 ...GROUPS_FILTER_DEFAULT
132             };
133
134             const THEMES_DEFAULT = {
135                 light: "Light",
136                 rust: "Rust",
137                 coal: "Coal",
138                 navy: "Navy",
139                 ayu: "Ayu"
140             };
141             $scope.themes = THEMES_DEFAULT;
142
143             $scope.versionFilters = {
144                 "≥": {enabled: false, minorVersion: null },
145                 "≤": {enabled: false, minorVersion: null },
146                 "=": {enabled: false, minorVersion: null },
147             };
148
149             $scope.selectTheme = function (theme) {
150                 setTheme(theme, true);
151             }
152
153             $scope.toggleLevels = function (value) {
154                 const levels = $scope.levels;
155                 for (const key in levels) {
156                     if (levels.hasOwnProperty(key)) {
157                         levels[key] = value;
158                     }
159                 }
160             };
161
162             $scope.toggleGroups = function (value) {
163                 const groups = $scope.groups;
164                 for (const key in groups) {
165                     if (groups.hasOwnProperty(key)) {
166                         groups[key] = value;
167                     }
168                 }
169             };
170
171             $scope.resetGroupsToDefault = function () {
172                 const groups = $scope.groups;
173                 for (const [key, value] of Object.entries(GROUPS_FILTER_DEFAULT)) {
174                     groups[key] = value;
175                 }
176             };
177
178             $scope.selectedValuesCount = function (obj) {
179                 return Object.values(obj).filter(x => x).length;
180             }
181
182             $scope.clearVersionFilters = function () {
183                 for (let filter in $scope.versionFilters) {
184                     $scope.versionFilters[filter] = { enabled: false, minorVersion: null };
185                 }
186             }
187
188             $scope.versionFilterCount = function(obj) {
189                 return Object.values(obj).filter(x => x.enabled).length;
190             }
191
192             $scope.updateVersionFilters = function() {
193                 for (const filter in $scope.versionFilters) {
194                     let minorVersion = $scope.versionFilters[filter].minorVersion;
195
196                     // 1.29.0 and greater
197                     if (minorVersion && minorVersion > 28) {
198                         $scope.versionFilters[filter].enabled = true;
199                         continue;
200                     }
201
202                     $scope.versionFilters[filter].enabled = false;
203                 }
204             }
205
206             $scope.byVersion = function(lint) {
207                 let filters = $scope.versionFilters;
208                 for (const filter in filters) {
209                     if (filters[filter].enabled) {
210                         let minorVersion = filters[filter].minorVersion;
211
212                         // Strip the "pre " prefix for pre 1.29.0 lints
213                         let lintVersion = lint.version.startsWith("pre ") ? lint.version.substring(4, lint.version.length) : lint.version;
214                         let lintMinorVersion = lintVersion.substring(2, 4);
215
216                         switch (filter) {
217                             // "=" gets the highest priority, since all filters are inclusive
218                             case "=":
219                                 return (lintMinorVersion == minorVersion);
220                             case "≥":
221                                 if (lintMinorVersion < minorVersion) { return false; }
222                                 break;
223                             case "≤":
224                                 if (lintMinorVersion > minorVersion) { return false; }
225                                 break;
226                             default:
227                                 return true
228                         }
229                     }
230                 }
231
232                 return true;
233             }
234
235             $scope.byGroups = function (lint) {
236                 return $scope.groups[lint.group];
237             };
238
239             $scope.bySearch = function (lint, index, array) {
240                 let searchStr = $scope.search;
241                 // It can be `null` I haven't missed this value
242                 if (searchStr == null || searchStr.length < 3) {
243                     return true;
244                 }
245                 searchStr = searchStr.toLowerCase();
246                 if (searchStr.startsWith("clippy::")) {
247                     searchStr = searchStr.slice(8);
248                 }
249
250                 // Search by id
251                 if (lint.id.indexOf(searchStr.replace("-", "_")) !== -1) {
252                     return true;
253                 }
254
255                 // Search the description
256                 // The use of `for`-loops instead of `foreach` enables us to return early
257                 let terms = searchStr.split(" ");
258                 let docsLowerCase = lint.docs.toLowerCase();
259                 for (index = 0; index < terms.length; index++) {
260                     // This is more likely and will therefor be checked first
261                     if (docsLowerCase.indexOf(terms[index]) !== -1) {
262                         continue;
263                     }
264
265                     if (lint.id.indexOf(terms[index]) !== -1) {
266                         continue;
267                     }
268
269                     return false;
270                 }
271
272                 return true;
273             }
274
275             $scope.copyToClipboard = function (lint) {
276                 const clipboard = document.getElementById("clipboard-" + lint.id);
277                 if (clipboard) {
278                     let resetClipboardTimeout = null;
279                     let resetClipboardIcon = clipboard.innerHTML;
280
281                     function resetClipboard() {
282                         resetClipboardTimeout = null;
283                         clipboard.innerHTML = resetClipboardIcon;
284                     }
285
286                     navigator.clipboard.writeText("clippy::" + lint.id);
287
288                     clipboard.innerHTML = "&#10003;";
289                     if (resetClipboardTimeout !== null) {
290                         clearTimeout(resetClipboardTimeout);
291                     }
292                     resetClipboardTimeout = setTimeout(resetClipboard, 1000);
293                 }
294             }
295
296             // Get data
297             $scope.open = {};
298             $scope.loading = true;
299             // This will be used to jump into the source code of the version that this documentation is for.
300             $scope.docVersion = window.location.pathname.split('/')[2] || "master";
301
302             if (window.location.hash.length > 1) {
303                 $scope.search = window.location.hash.slice(1);
304                 $scope.open[window.location.hash.slice(1)] = true;
305                 scrollToLintByURL($scope);
306             }
307
308             $http.get('./lints.json')
309                 .success(function (data) {
310                     $scope.data = data;
311                     $scope.loading = false;
312
313                     var selectedGroup = getQueryVariable("sel");
314                     if (selectedGroup) {
315                         selectGroup($scope, selectedGroup.toLowerCase());
316                     }
317
318                     scrollToLintByURL($scope);
319
320                     setTimeout(function () {
321                         var el = document.getElementById('filter-input');
322                         if (el) { el.focus() }
323                     }, 0);
324                 })
325                 .error(function (data) {
326                     $scope.error = data;
327                     $scope.loading = false;
328                 });
329
330             window.addEventListener('hashchange', function () {
331                 // trigger re-render
332                 $timeout(function () {
333                     $scope.levels = LEVEL_FILTERS_DEFAULT;
334                     $scope.search = window.location.hash.slice(1);
335                     $scope.open[window.location.hash.slice(1)] = true;
336
337                     scrollToLintByURL($scope);
338                 });
339                 return true;
340             }, false);
341         });
342 })();
343
344 function getQueryVariable(variable) {
345     var query = window.location.search.substring(1);
346     var vars = query.split('&');
347     for (var i = 0; i < vars.length; i++) {
348         var pair = vars[i].split('=');
349         if (decodeURIComponent(pair[0]) == variable) {
350             return decodeURIComponent(pair[1]);
351         }
352     }
353 }
354
355 function setTheme(theme, store) {
356     let enableHighlight = false;
357     let enableNight = false;
358     let enableAyu = false;
359
360     switch(theme) {
361         case "ayu":
362             enableAyu = true;
363             break;
364         case "coal":
365         case "navy":
366             enableNight = true;
367             break;
368         case "rust":
369             enableHighlight = true;
370             break;
371         default:
372             enableHighlight = true;
373             theme = "light";
374             break;
375     }
376
377     document.getElementsByTagName("body")[0].className = theme;
378
379     document.getElementById("githubLightHighlight").disabled = enableNight || !enableHighlight;
380     document.getElementById("githubDarkHighlight").disabled = !enableNight && !enableAyu;
381
382     document.getElementById("styleHighlight").disabled = !enableHighlight;
383     document.getElementById("styleNight").disabled = !enableNight;
384     document.getElementById("styleAyu").disabled = !enableAyu;
385
386     if (store) {
387         try {
388             localStorage.setItem('clippy-lint-list-theme', theme);
389         } catch (e) { }
390     }
391 }
392
393 // loading the theme after the initial load
394 const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
395 const theme = localStorage.getItem('clippy-lint-list-theme');
396 if (prefersDark.matches && !theme) {
397     setTheme("coal", false);
398 } else {
399     setTheme(theme, false);
400 }