diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2024-08-12 20:39:25 +0200 |
|---|---|---|
| committer | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2024-09-22 22:30:44 +0200 |
| commit | b522e7a944341d463bf9091bd72faffcc807d875 (patch) | |
| tree | e6573de0fb3d8c6b4d93bfd5d4d88990256e6efd | |
| parent | 43e338458168db91b8459735ba6ac0f230d78d92 (diff) | |
| download | rust-b522e7a944341d463bf9091bd72faffcc807d875.tar.gz rust-b522e7a944341d463bf9091bd72faffcc807d875.zip | |
Generate lint list in HTML directly instead of JS
| -rw-r--r-- | .github/deploy.sh | 1 | ||||
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | clippy_dev/src/serve.rs | 2 | ||||
| -rw-r--r-- | rinja.toml | 8 | ||||
| -rw-r--r-- | tests/compile-test.rs | 33 | ||||
| -rw-r--r-- | util/gh-pages/index_template.html (renamed from util/gh-pages/index.html) | 103 | ||||
| -rw-r--r-- | util/gh-pages/script.js | 108 |
8 files changed, 152 insertions, 106 deletions
diff --git a/.github/deploy.sh b/.github/deploy.sh index 5b4b4be4e36..6cebbb7801b 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -9,7 +9,6 @@ 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 cp util/gh-pages/style.css out/master if [[ -n $TAG_NAME ]]; then diff --git a/.gitignore b/.gitignore index 181b71a658b..a7c25b29021 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ out # gh pages docs util/gh-pages/lints.json +util/gh-pages/index.html # rustfmt backups *.rs.bk diff --git a/Cargo.toml b/Cargo.toml index cf810798d8c..c7383520741 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,8 @@ toml = "0.7.3" walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" +pulldown-cmark = "0.11" +rinja = { version = "0.3", default-features = false, features = ["config"] } # UI test dependencies clippy_utils = { path = "clippy_utils" } diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs index cc14cd8dae6..0216d884e2d 100644 --- a/clippy_dev/src/serve.rs +++ b/clippy_dev/src/serve.rs @@ -19,7 +19,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! { }); loop { - if mtime("util/gh-pages/lints.json") < mtime("clippy_lints/src") { + if mtime("util/gh-pages/index.html") < mtime("clippy_lints/src") { Command::new(env::var("CARGO").unwrap_or("cargo".into())) .arg("collect-metadata") .spawn() diff --git a/rinja.toml b/rinja.toml new file mode 100644 index 00000000000..5fa682788bd --- /dev/null +++ b/rinja.toml @@ -0,0 +1,8 @@ +[general] +dirs = ["util/gh-pages/"] +default_syntax = "mixed" + +[[syntax]] +name = "mixed" +expr_start = "{(" +expr_end = ")}" diff --git a/tests/compile-test.rs b/tests/compile-test.rs index af2aa519257..0bd6ac67770 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -8,6 +8,8 @@ use clippy_config::ClippyConfiguration; use clippy_lints::LintInfo; use clippy_lints::declared_lints::LINTS; use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; +use pulldown_cmark::{Options, Parser, html}; +use rinja::{Template, filters::Safe}; use serde::{Deserialize, Serialize}; use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; @@ -385,6 +387,22 @@ fn ui_cargo_toml_metadata() { } } +#[derive(Template)] +#[template(path = "index_template.html")] +struct Renderer<'a> { + lints: &'a Vec<LintMetadata>, +} + +impl<'a> Renderer<'a> { + fn markdown(&self, input: &str) -> Safe<String> { + let parser = Parser::new_ext(input, Options::all()); + let mut html_output = String::new(); + html::push_html(&mut html_output, parser); + // Oh deer, what a hack :O + Safe(html_output.replace("<table", "<table class=\"table\"")) + } +} + #[derive(Deserialize)] #[serde(untagged)] enum DiagnosticOrMessage { @@ -447,8 +465,7 @@ impl DiagnosticCollector { .collect(); metadata.sort_unstable_by(|a, b| a.id.cmp(&b.id)); - let json = serde_json::to_string_pretty(&metadata).unwrap(); - fs::write("util/gh-pages/lints.json", json).unwrap(); + fs::write("util/gh-pages/index.html", Renderer { lints: &metadata }.render().unwrap()).unwrap(); }); (Self { sender }, handle) @@ -487,7 +504,7 @@ impl Flag for DiagnosticCollector { } } -#[derive(Debug, Serialize)] +#[derive(Debug)] struct LintMetadata { id: String, id_location: Option<&'static str>, @@ -559,4 +576,14 @@ impl LintMetadata { applicability: Applicability::Unspecified, } } + + fn applicability_str(&self) -> &str { + match self.applicability { + Applicability::MachineApplicable => "MachineApplicable", + Applicability::HasPlaceholders => "HasPlaceholders", + Applicability::MaybeIncorrect => "MaybeIncorrect", + Applicability::Unspecified => "Unspecified", + _ => panic!("needs to update this code"), + } + } } diff --git a/util/gh-pages/index.html b/util/gh-pages/index_template.html index f3d7e504fdf..ee134eaaa98 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index_template.html @@ -55,16 +55,8 @@ Otherwise, have a great day =^.^= </div> </noscript> - <div ng-cloak> - - <div class="alert alert-info" role="alert" ng-if="loading"> - Loading… - </div> - <div class="alert alert-danger" role="alert" ng-if="error"> - Error loading lints! - </div> - - <div class="panel panel-default" ng-show="data"> + <div> + <div class="panel panel-default"> <div class="panel-body row"> <div id="upper-filters" class="col-12 col-md-5"> <div class="btn-group" filter-dropdown> @@ -188,9 +180,7 @@ Otherwise, have a great day =^.^= <div class="col-12 col-md-5 search-control"> <div class="input-group"> <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 (`S` or `/` to focus)" id="search-input" - ng-model="search" ng-blur="updatePath()" ng-keyup="$event.keyCode == 13 && updatePath()" - ng-model-options="{debounce: 50}" /> + <input type="text" class="form-control filter-input" placeholder="Keywords or search string (`S` or `/` to focus)" id="search-input" onblur="updatePath()" onchange="handleInputChanged()" /> <span class="input-group-btn"> <button class="filter-clear btn" type="button" ng-click="search = ''; updatePath();"> Clear @@ -208,56 +198,57 @@ Otherwise, have a great day =^.^= </div> </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 | filter:byVersion | filter:byApplicabilities"> - <header class="panel-heading" ng-click="open[lint.id] = !open[lint.id]"> - <h2 class="panel-title"> - <div class="panel-title-name"> - <span>{{lint.id}}</span> - <a href="#{{lint.id}}" class="anchor label label-default" - ng-click="openLint(lint); $event.preventDefault(); $event.stopPropagation()">¶</a> - <a href="" id="clipboard-{{lint.id}}" class="anchor label label-default" ng-click="copyToClipboard(lint); $event.stopPropagation()"> - 📋 - </a> - </div> + {% for lint in lints %} + <article class="panel panel-default" id="{{lint.id}}"> + <header class="panel-heading" ng-click="open[lint.id] = !open[lint.id]"> + <h2 class="panel-title"> + <div class="panel-title-name"> + <span>{(lint.id)}</span> + <a href="#{{lint.id}}" class="anchor label label-default" + ng-click="openLint(lint); $event.preventDefault(); $event.stopPropagation()">¶</a> + <a href="" id="clipboard-{{lint.id}}" class="anchor label label-default" ng-click="copyToClipboard(lint); $event.stopPropagation()"> + 📋 + </a> + </div> - <div class="panel-title-addons"> - <span class="label label-lint-group label-default label-group-{{lint.group}}">{{lint.group}}</span> + <div class="panel-title-addons"> + <span class="label label-lint-group label-default label-group-{{lint.group}}">{(lint.group)}</span> - <span class="label label-lint-level label-lint-level-{{lint.level}}">{{lint.level}}</span> + <span class="label label-lint-level label-lint-level-{{lint.level}}">{(lint.level)}</span> - <span class="label label-doc-folding" ng-show="open[lint.id]">−</span> - <span class="label label-doc-folding" ng-hide="open[lint.id]">+</span> - </div> - </h2> - </header> + <span class="label label-doc-folding" ng-show="open[lint.id]">−</span> + <span class="label label-doc-folding" ng-hide="open[lint.id]">+</span> + </div> + </h2> + </header> - <div class="list-group lint-docs" ng-if="open[lint.id]" ng-class="{collapse: true, in: open[lint.id]}"> - <div class="list-group-item lint-doc-md" ng-bind-html="lint.docs | markdown"></div> - <div class="lint-additional-info-container"> - <!-- Applicability --> - <div class="lint-additional-info-item"> - <span> Applicability: </span> - <span class="label label-default label-applicability">{{lint.applicability}}</span> - <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.Applicability.html#variants">(?)</a> - </div> - <!-- Clippy version --> - <div class="lint-additional-info-item"> - <span>{{lint.group == "deprecated" ? "Deprecated" : "Added"}} in: </span> - <span class="label label-default label-version">{{lint.version}}</span> - </div> - <!-- Open related issues --> - <div class="lint-additional-info-item"> - <a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a> - </div> - <!-- Jump to source --> - <div class="lint-additional-info-item" ng-if="lint.id_location"> - <a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/{{lint.id_location}}">View Source</a> + <div class="list-group lint-docs" ng-class="{collapse: true, in: open[lint.id]}"> + <div class="list-group-item lint-doc-md">{(markdown(lint.docs))}</div> + <div class="lint-additional-info-container"> + {# Applicability #} + <div class="lint-additional-info-item"> + <span> Applicability: </span> + <span class="label label-default label-applicability">{( lint.applicability_str() )}</span> + <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.Applicability.html#variants">(?)</a> + </div> + <!-- Clippy version --> + <div class="lint-additional-info-item"> + <span>{% if lint.group == "deprecated" %}Deprecated{% else %} Added{% endif %} in: </span> + <span class="label label-default label-version">{(lint.version)}</span> + </div> + <!-- Open related issues --> + <div class="lint-additional-info-item"> + <a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a> + </div> + <!-- Jump to source --> + <div class="lint-additional-info-item" ng-if="lint.id_location"> + <a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/clippy_lints/{{lint.id_location.path}}">View Source</a> + </div> </div> </div> - </div> - </article> + </article> + {% endfor %} </div> </div> diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 1a5330bc0e5..8942628d5da 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -1,21 +1,4 @@ (function () { - const 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(str, { language: lang, ignoreIllegals: true }).value + - '</code></pre>'; - } catch (__) {} - } - - return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'; - } - }); - function scrollToLint(lintId) { const target = document.getElementById(lintId); if (!target) { @@ -41,15 +24,6 @@ } 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('filterDropdown', function ($document) { return { restrict: 'A', @@ -470,27 +444,17 @@ // Set up the filters from the URL parameters before we start loading the data loadFromURLParameters(); - $http.get('./lints.json') - .success(function (data) { - $scope.data = data; - $scope.loading = false; - - const selectedGroup = getQueryVariable("sel"); - if (selectedGroup) { - selectGroup($scope, selectedGroup.toLowerCase()); - } + const selectedGroup = getQueryVariable("sel"); + if (selectedGroup) { + selectGroup($scope, selectedGroup.toLowerCase()); + } - scrollToLintByURL($scope, $location); + scrollToLintByURL($scope, $location); - setTimeout(function () { - const el = document.getElementById('filter-input'); - if (el) { el.focus() } - }, 0); - }) - .error(function (data) { - $scope.error = data; - $scope.loading = false; - }); + setTimeout(function () { + const el = document.getElementById('filter-input'); + if (el) { el.focus() } + }, 0); }); })(); @@ -505,6 +469,58 @@ function getQueryVariable(variable) { } } +window.searchState = { + timeout: null, + inputElem: document.getElementById("search-input"), + clearInputTimeout: () => { + if (searchState.timeout !== null) { + clearTimeout(searchState.timeout); + searchState.timeout = null + } + }, + resetInputTimeout: () => { + searchState.clearInputTimeout(); + setTimeout(searchState.filterLints, 50); + }, + filterLints: () => { + let searchStr = searchState.value.trim().toLowerCase(); + if (searchStr.startsWith("clippy::")) { + searchStr = searchStr.slice(8); + } + const terms = searchStr.split(" "); + + onEachLazy(document.querySelectorAll("article"), lint => { + // Search by id + if (lint.id.indexOf(searchStr.replaceAll("-", "_")) !== -1) { + el.style.display = ""; + return; + } + // Search the description + // The use of `for`-loops instead of `foreach` enables us to return early + const docsLowerCase = lint.docs.toLowerCase(); + for (index = 0; index < terms.length; index++) { + // This is more likely and will therefore be checked first + if (docsLowerCase.indexOf(terms[index]) !== -1) { + continue; + } + + if (lint.id.indexOf(terms[index]) !== -1) { + continue; + } + + return false; + } + }); + }, +}; + +function handleInputChanged(event) { + if (event.target !== document.activeElement) { + return; + } + searchState.resetInputTimeout(); +} + function storeValue(settingName, value) { try { localStorage.setItem(`clippy-lint-list-${settingName}`, value); @@ -627,3 +643,5 @@ if (prefersDark.matches && !theme) { } let disableShortcuts = loadValue('disable-shortcuts') === "true"; document.getElementById("disable-shortcuts").checked = disableShortcuts; + +hljs.highlightAll(); |
