diff options
| author | bors <bors@rust-lang.org> | 2022-05-16 17:49:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-05-16 17:49:00 +0000 |
| commit | 6e86ab007cdcebd5fce87a598f7be9169080934e (patch) | |
| tree | 9266c078381fa10f7dc7be143ffbbb62edb55c34 | |
| parent | a1632fffc13b35be1b58b24edabed9cada06b160 (diff) | |
| parent | f112e4d445006426830752e23c716efb835acea5 (diff) | |
| download | rust-6e86ab007cdcebd5fce87a598f7be9169080934e.tar.gz rust-6e86ab007cdcebd5fce87a598f7be9169080934e.zip | |
Auto merge of #8752 - Serial-ATA:improve-filtering, r=xFrednet
Add version filtering option to the lint list I'm no web dev, so I don't know if this is the best execution :smile:. Here's how it looks:  And on mobile:  I've split this into two commits, in the second one I moved the JS into its own file to make it easier to work on. Is that alright? And if so, could the same thing be done to the css? changelog: none cc: #7958, `@repi` r? `@xFrednet`
| -rw-r--r-- | .github/deploy.sh | 1 | ||||
| -rw-r--r-- | util/gh-pages/index.html | 393 | ||||
| -rw-r--r-- | util/gh-pages/script.js | 350 |
3 files changed, 442 insertions, 302 deletions
diff --git a/.github/deploy.sh b/.github/deploy.sh index 34225a54029..5a59f94ec91 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -8,6 +8,7 @@ rm -rf out/master/ || exit 0 echo "Making the docs for master" mkdir out/master/ cp util/gh-pages/index.html out/master +cp util/gh-pages/script.js out/master cp util/gh-pages/lints.json out/master if [[ -n $TAG_NAME ]]; then diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 97c974003c6..1171da3f4e5 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -94,6 +94,29 @@ Otherwise, have a great day =^.^= @media (min-width: 992px) { .search-control { margin-top: 0; + float: right; + } + } + + @media (min-width: 405px) { + #upper-filters { + display: flex; + } + } + + @media (max-width: 430px) { + /* Turn the version filter list to the left */ + #version-filter-selector { + right: 0; + left: auto; + } + } + + @media (max-width: 412px) { + #upper-filters, + .panel-body .search-control { + padding-right: 8px; + padding-left: 8px; } } @@ -244,7 +267,7 @@ Otherwise, have a great day =^.^= cursor: pointer; } - .theme-choice>li:hover { + .theme-choice > li:hover { background: var(--theme-hover); } @@ -273,23 +296,44 @@ Otherwise, have a great day =^.^= border: 1px solid var(--theme-popup-border); } - #filter-label, #filter-clear { + #version-filter-selector .checkbox { + display: flex; + } + + #version-filter { + min-width: available; + } + + #version-filter li label { + padding-right: 0; + width: 35%; + } + + .version-filter-input { + height: 60%; + width: 30%; + text-align: center; + border: none; + border-bottom: 1px solid #000000; + } + + #filter-label, .filter-clear { background: var(--searchbar-bg); color: var(--searchbar-fg); border-color: var(--theme-popup-border); filter: brightness(95%); } - #filter-label:hover, #filter-clear:hover { + #filter-label:hover, .filter-clear:hover { filter: brightness(90%); } - #filter-input { + .filter-input { background: var(--searchbar-bg); color: var(--searchbar-fg); border-color: var(--theme-popup-border); } - #filter-input::-webkit-input-placeholder, - #filter-input::-moz-placeholder { + .filter-input::-webkit-input-placeholder, + .filter-input::-moz-placeholder { color: var(--searchbar-fg); opacity: 30%; } @@ -338,7 +382,7 @@ Otherwise, have a great day =^.^= <div class="panel panel-default" ng-show="data"> <div class="panel-body row"> - <div class="col-12 col-md-4"> + <div id="upper-filters" class="col-12 col-md-4"> <div class="btn-group" filter-dropdown> <button type="button" class="btn btn-default dropdown-toggle"> Lint levels <span class="badge">{{selectedValuesCount(levels)}}</span> <span class="caret"></span> @@ -391,13 +435,47 @@ Otherwise, have a great day =^.^= </li> </ul> </div> + <div id="version-filter"> + <div class="btn-group" filter-dropdown> + <button type="button" class="btn btn-default dropdown-toggle"> + Version + <span id="version-filter-count" class="badge"> + {{versionFilterCount(versionFilters)}} + </span> + <span class="caret"></span> + </button> + <ul id="version-filter-selector" class="dropdown-menu"> + <li class="checkbox"> + <label ng-click="clearVersionFilters()"> + <input type="checkbox" class="invisible" /> + Clear filters + </label> + </li> + <li role="separator" class="divider"></li> + <li class="checkbox" ng-repeat="(filter, vars) in versionFilters"> + <label ng-attr-for="filter-{filter}">{{filter}}</label> + <span>1.</span> + <input type="number" + min="29" + ng-attr-id="filter-{filter}" + class="version-filter-input form-control filter-input" + maxlength="2" + ng-model="versionFilters[filter].minorVersion" + ng-model-options="{debounce: 50}" + ng-change="updateVersionFilters()" /> + <span>.0</span> + </li> + </ul> + </div> + </div> + </div> - <div class="col-12 col-md-8 search-control"> + <div class="col-12 col-md-7 search-control"> <div class="input-group"> - <label class="input-group-addon" id="filter-label" for="filter-input">Filter:</label> - <input type="text" class="form-control" placeholder="Keywords or search string" id="filter-input" ng-model="search" ng-model-options="{debounce: 50}"/> + <label class="input-group-addon" id="filter-label" for="search-input">Filter:</label> + <input type="text" class="form-control filter-input" placeholder="Keywords or search string" id="search-input" ng-model="search" ng-model-options="{debounce: 50}"/> <span class="input-group-btn"> - <button id="filter-clear" class="btn" type="button" ng-click="search = ''"> + <button class="filter-clear btn" type="button" ng-click="search = ''"> Clear </button> </span> @@ -406,7 +484,7 @@ Otherwise, have a great day =^.^= </div> </div> <!-- The order of the filters should be from most likely to remove a lint to least likely to improve performance. --> - <article class="panel panel-default" id="{{lint.id}}" ng-repeat="lint in data | filter:bySearch | filter:byGroups | filter:byLevels"> + <article class="panel panel-default" id="{{lint.id}}" ng-repeat="lint in data | filter:bySearch | filter:byGroups | filter:byLevels | filter:byVersion"> <header class="panel-heading" ng-click="open[lint.id] = !open[lint.id]"> <h2 class="panel-title"> <div class="panel-title-name"> @@ -462,295 +540,6 @@ Otherwise, have a great day =^.^= <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.5.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.5.0/languages/rust.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.12/angular.min.js"></script> - <script> - (function () { - var md = window.markdownit({ - html: true, - linkify: true, - typographer: true, - highlight: function (str, lang) { - if (lang && hljs.getLanguage(lang)) { - try { - return '<pre class="hljs"><code>' + - hljs.highlight(lang, str, true).value + - '</code></pre>'; - } catch (__) {} - } - - return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'; - } - }); - - function scrollToLint(lintId) { - var target = document.getElementById(lintId); - if (!target) { - return; - } - target.scrollIntoView(); - } - - function scrollToLintByURL($scope) { - var removeListener = $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) { - scrollToLint(window.location.hash.slice(1)); - removeListener(); - }); - } - - function selectGroup($scope, selectedGroup) { - var groups = $scope.groups; - for (var group in groups) { - if (groups.hasOwnProperty(group)) { - if (group === selectedGroup) { - groups[group] = true; - } else { - groups[group] = false; - } - } - } - } - - angular.module("clippy", []) - .filter('markdown', function ($sce) { - return function (text) { - return $sce.trustAsHtml( - md.render(text || '') - // Oh deer, what a hack :O - .replace('<table', '<table class="table"') - ); - }; - }) - .directive('themeDropdown', function ($document) { - return { - restrict: 'A', - link: function ($scope, $element, $attr) { - $element.bind('click', function () { - $element.toggleClass('open'); - $element.addClass('open-recent'); - }); - - $document.bind('click', function () { - if (!$element.hasClass('open-recent')) { - $element.removeClass('open'); - } - $element.removeClass('open-recent'); - }) - } - } - }) - .directive('filterDropdown', function ($document) { - return { - restrict: 'A', - link: function ($scope, $element, $attr) { - $element.bind('click', function (event) { - if (event.target.closest('button')) { - $element.toggleClass('open'); - } else { - $element.addClass('open'); - } - $element.addClass('open-recent'); - }); - - $document.bind('click', function () { - if (!$element.hasClass('open-recent')) { - $element.removeClass('open'); - } - $element.removeClass('open-recent'); - }) - } - } - }) - .directive('onFinishRender', function ($timeout) { - return { - restrict: 'A', - link: function (scope, element, attr) { - if (scope.$last === true) { - $timeout(function () { - scope.$emit(attr.onFinishRender); - }); - } - } - }; - }) - .controller("lintList", function ($scope, $http, $timeout) { - // Level filter - var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true}; - $scope.levels = LEVEL_FILTERS_DEFAULT; - $scope.byLevels = function (lint) { - return $scope.levels[lint.level]; - }; - - var GROUPS_FILTER_DEFAULT = { - cargo: true, - complexity: true, - correctness: true, - deprecated: false, - nursery: true, - pedantic: true, - perf: true, - restriction: true, - style: true, - suspicious: true, - }; - $scope.groups = GROUPS_FILTER_DEFAULT; - const THEMES_DEFAULT = { - light: "Light", - rust: "Rust", - coal: "Coal", - navy: "Navy", - ayu: "Ayu" - }; - $scope.themes = THEMES_DEFAULT; - - $scope.selectTheme = function (theme) { - setTheme(theme, true); - } - - $scope.toggleLevels = function (value) { - const levels = $scope.levels; - for (const key in levels) { - if (levels.hasOwnProperty(key)) { - levels[key] = value; - } - } - }; - $scope.toggleGroups = function (value) { - const groups = $scope.groups; - for (const key in groups) { - if (groups.hasOwnProperty(key)) { - groups[key] = value; - } - } - }; - $scope.selectedValuesCount = function (obj) { - return Object.values(obj).filter(x => x).length; - } - $scope.byGroups = function (lint) { - return $scope.groups[lint.group]; - }; - - $scope.bySearch = function (lint, index, array) { - let searchStr = $scope.search; - // It can be `null` I haven't missed this value - if (searchStr == null || searchStr.length < 3) { - return true; - } - searchStr = searchStr.toLowerCase(); - - // Search by id - if (lint.id.indexOf(searchStr.replace("-", "_")) !== -1) { - return true; - } - - // Search the description - // The use of `for`-loops instead of `foreach` enables us to return early - let terms = searchStr.split(" "); - let docsLowerCase = lint.docs.toLowerCase(); - for (index = 0; index < terms.length; index++) { - // This is more likely and will therefor be checked first - if (docsLowerCase.indexOf(terms[index]) !== -1) { - continue; - } - - if (lint.id.indexOf(terms[index]) !== -1) { - continue; - } - - return false; - } - - return true; - } - - // Get data - $scope.open = {}; - $scope.loading = true; - // This will be used to jump into the source code of the version that this documentation is for. - $scope.docVersion = window.location.pathname.split('/')[2] || "master"; - - if (window.location.hash.length > 1) { - $scope.search = window.location.hash.slice(1); - $scope.open[window.location.hash.slice(1)] = true; - scrollToLintByURL($scope); - } - - $http.get('./lints.json') - .success(function (data) { - $scope.data = data; - $scope.loading = false; - - var selectedGroup = getQueryVariable("sel"); - if (selectedGroup) { - selectGroup($scope, selectedGroup.toLowerCase()); - } - - scrollToLintByURL($scope); - - setTimeout(function () { - var el = document.getElementById('filter-input'); - if (el) { el.focus() } - }, 0); - }) - .error(function (data) { - $scope.error = data; - $scope.loading = false; - }); - - window.addEventListener('hashchange', function () { - // trigger re-render - $timeout(function () { - $scope.levels = LEVEL_FILTERS_DEFAULT; - $scope.search = window.location.hash.slice(1); - $scope.open[window.location.hash.slice(1)] = true; - - scrollToLintByURL($scope); - }); - return true; - }, false); - }); - })(); - - function getQueryVariable(variable) { - var query = window.location.search.substring(1); - var vars = query.split('&'); - for (var i = 0; i < vars.length; i++) { - var pair = vars[i].split('='); - if (decodeURIComponent(pair[0]) == variable) { - return decodeURIComponent(pair[1]); - } - } - } - - function setTheme(theme, store) { - let enableHighlight = false; - let enableNight = false; - let enableAyu = false; - - if (theme == "ayu") { - enableAyu = true; - } else if (theme == "coal" || theme == "navy") { - enableNight = true; - } else if (theme == "rust") { - enableHighlight = true; - } else { - enableHighlight = true; - // this makes sure that an unknown theme request gets set to a known one - theme = "light"; - } - document.getElementsByTagName("body")[0].className = theme; - - document.getElementById("styleHighlight").disabled = !enableHighlight; - document.getElementById("styleNight").disabled = !enableNight; - document.getElementById("styleAyu").disabled = !enableAyu; - - if (store) { - try { - localStorage.setItem('clippy-lint-list-theme', theme); - } catch (e) { } - } - } - - // loading the theme after the initial load - setTheme(localStorage.getItem('clippy-lint-list-theme'), false); - </script> + <script src="script.js"></script> </body> </html> diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js new file mode 100644 index 00000000000..c3250afdea2 --- /dev/null +++ b/util/gh-pages/script.js @@ -0,0 +1,350 @@ +(function () { + var md = window.markdownit({ + html: true, + linkify: true, + typographer: true, + highlight: function (str, lang) { + if (lang && hljs.getLanguage(lang)) { + try { + return '<pre class="hljs"><code>' + + hljs.highlight(lang, str, true).value + + '</code></pre>'; + } catch (__) {} + } + + return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'; + } + }); + + function scrollToLint(lintId) { + var target = document.getElementById(lintId); + if (!target) { + return; + } + target.scrollIntoView(); + } + + function scrollToLintByURL($scope) { + var removeListener = $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) { + scrollToLint(window.location.hash.slice(1)); + removeListener(); + }); + } + + function selectGroup($scope, selectedGroup) { + var groups = $scope.groups; + for (var group in groups) { + if (groups.hasOwnProperty(group)) { + if (group === selectedGroup) { + groups[group] = true; + } else { + groups[group] = false; + } + } + } + } + + angular.module("clippy", []) + .filter('markdown', function ($sce) { + return function (text) { + return $sce.trustAsHtml( + md.render(text || '') + // Oh deer, what a hack :O + .replace('<table', '<table class="table"') + ); + }; + }) + .directive('themeDropdown', function ($document) { + return { + restrict: 'A', + link: function ($scope, $element, $attr) { + $element.bind('click', function () { + $element.toggleClass('open'); + $element.addClass('open-recent'); + }); + + $document.bind('click', function () { + if (!$element.hasClass('open-recent')) { + $element.removeClass('open'); + } + $element.removeClass('open-recent'); + }) + } + } + }) + .directive('filterDropdown', function ($document) { + return { + restrict: 'A', + link: function ($scope, $element, $attr) { + $element.bind('click', function (event) { + if (event.target.closest('button')) { + $element.toggleClass('open'); + } else { + $element.addClass('open'); + } + $element.addClass('open-recent'); + }); + + $document.bind('click', function () { + if (!$element.hasClass('open-recent')) { + $element.removeClass('open'); + } + $element.removeClass('open-recent'); + }) + } + } + }) + .directive('onFinishRender', function ($timeout) { + return { + restrict: 'A', + link: function (scope, element, attr) { + if (scope.$last === true) { + $timeout(function () { + scope.$emit(attr.onFinishRender); + }); + } + } + }; + }) + .controller("lintList", function ($scope, $http, $timeout) { + // Level filter + var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true}; + $scope.levels = LEVEL_FILTERS_DEFAULT; + $scope.byLevels = function (lint) { + return $scope.levels[lint.level]; + }; + + var GROUPS_FILTER_DEFAULT = { + cargo: true, + complexity: true, + correctness: true, + deprecated: false, + nursery: true, + pedantic: true, + perf: true, + restriction: true, + style: true, + suspicious: true, + }; + $scope.groups = GROUPS_FILTER_DEFAULT; + const THEMES_DEFAULT = { + light: "Light", + rust: "Rust", + coal: "Coal", + navy: "Navy", + ayu: "Ayu" + }; + $scope.themes = THEMES_DEFAULT; + + $scope.versionFilters = { + "≥": {enabled: false, minorVersion: null }, + "≤": {enabled: false, minorVersion: null }, + "=": {enabled: false, minorVersion: null }, + }; + + $scope.selectTheme = function (theme) { + setTheme(theme, true); + } + + $scope.toggleLevels = function (value) { + const levels = $scope.levels; + for (const key in levels) { + if (levels.hasOwnProperty(key)) { + levels[key] = value; + } + } + }; + + $scope.toggleGroups = function (value) { + const groups = $scope.groups; + for (const key in groups) { + if (groups.hasOwnProperty(key)) { + groups[key] = value; + } + } + }; + + $scope.selectedValuesCount = function (obj) { + return Object.values(obj).filter(x => x).length; + } + + $scope.clearVersionFilters = function () { + for (let filter in $scope.versionFilters) { + $scope.versionFilters[filter] = { enabled: false, minorVersion: null }; + } + } + + $scope.versionFilterCount = function(obj) { + return Object.values(obj).filter(x => x.enabled).length; + } + + $scope.updateVersionFilters = function() { + for (const filter in $scope.versionFilters) { + let minorVersion = $scope.versionFilters[filter].minorVersion; + + // 1.29.0 and greater + if (minorVersion && minorVersion > 28) { + $scope.versionFilters[filter].enabled = true; + continue; + } + + $scope.versionFilters[filter].enabled = false; + } + } + + $scope.byVersion = function(lint) { + let filters = $scope.versionFilters; + for (const filter in filters) { + if (filters[filter].enabled) { + let minorVersion = filters[filter].minorVersion; + + // Strip the "pre " prefix for pre 1.29.0 lints + let lintVersion = lint.version.startsWith("pre ") ? lint.version.substring(4, lint.version.length) : lint.version; + let lintMinorVersion = lintVersion.substring(2, 4); + + switch (filter) { + // "=" gets the highest priority, since all filters are inclusive + case "=": + return (lintMinorVersion == minorVersion); + case "≥": + if (lintMinorVersion < minorVersion) { return false; } + break; + case "≤": + if (lintMinorVersion > minorVersion) { return false; } + break; + default: + return true + } + } + } + + return true; + } + + $scope.byGroups = function (lint) { + return $scope.groups[lint.group]; + }; + + $scope.bySearch = function (lint, index, array) { + let searchStr = $scope.search; + // It can be `null` I haven't missed this value + if (searchStr == null || searchStr.length < 3) { + return true; + } + searchStr = searchStr.toLowerCase(); + + // Search by id + if (lint.id.indexOf(searchStr.replace("-", "_")) !== -1) { + return true; + } + + // Search the description + // The use of `for`-loops instead of `foreach` enables us to return early + let terms = searchStr.split(" "); + let docsLowerCase = lint.docs.toLowerCase(); + for (index = 0; index < terms.length; index++) { + // This is more likely and will therefor be checked first + if (docsLowerCase.indexOf(terms[index]) !== -1) { + continue; + } + + if (lint.id.indexOf(terms[index]) !== -1) { + continue; + } + + return false; + } + + return true; + } + + // Get data + $scope.open = {}; + $scope.loading = true; + // This will be used to jump into the source code of the version that this documentation is for. + $scope.docVersion = window.location.pathname.split('/')[2] || "master"; + + if (window.location.hash.length > 1) { + $scope.search = window.location.hash.slice(1); + $scope.open[window.location.hash.slice(1)] = true; + scrollToLintByURL($scope); + } + + $http.get('./lints.json') + .success(function (data) { + $scope.data = data; + $scope.loading = false; + + var selectedGroup = getQueryVariable("sel"); + if (selectedGroup) { + selectGroup($scope, selectedGroup.toLowerCase()); + } + + scrollToLintByURL($scope); + + setTimeout(function () { + var el = document.getElementById('filter-input'); + if (el) { el.focus() } + }, 0); + }) + .error(function (data) { + $scope.error = data; + $scope.loading = false; + }); + + window.addEventListener('hashchange', function () { + // trigger re-render + $timeout(function () { + $scope.levels = LEVEL_FILTERS_DEFAULT; + $scope.search = window.location.hash.slice(1); + $scope.open[window.location.hash.slice(1)] = true; + + scrollToLintByURL($scope); + }); + return true; + }, false); + }); +})(); + +function getQueryVariable(variable) { + var query = window.location.search.substring(1); + var vars = query.split('&'); + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split('='); + if (decodeURIComponent(pair[0]) == variable) { + return decodeURIComponent(pair[1]); + } + } +} + +function setTheme(theme, store) { + let enableHighlight = false; + let enableNight = false; + let enableAyu = false; + + if (theme == "ayu") { + enableAyu = true; + } else if (theme == "coal" || theme == "navy") { + enableNight = true; + } else if (theme == "rust") { + enableHighlight = true; + } else { + enableHighlight = true; + // this makes sure that an unknown theme request gets set to a known one + theme = "light"; + } + document.getElementsByTagName("body")[0].className = theme; + + document.getElementById("styleHighlight").disabled = !enableHighlight; + document.getElementById("styleNight").disabled = !enableNight; + document.getElementById("styleAyu").disabled = !enableAyu; + + if (store) { + try { + localStorage.setItem('clippy-lint-list-theme', theme); + } catch (e) { } + } +} + +// loading the theme after the initial load +setTheme(localStorage.getItem('clippy-lint-list-theme'), false); |
