summaryrefslogtreecommitdiffstats
path: root/src/tools/html-checker/main.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/tools/html-checker/main.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/html-checker/main.rs')
-rw-r--r--src/tools/html-checker/main.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/tools/html-checker/main.rs b/src/tools/html-checker/main.rs
new file mode 100644
index 000000000..9b4d2c525
--- /dev/null
+++ b/src/tools/html-checker/main.rs
@@ -0,0 +1,125 @@
+use rayon::iter::{ParallelBridge, ParallelIterator};
+use std::env;
+use std::path::Path;
+use std::process::{Command, Output};
+
+fn check_html_file(file: &Path) -> usize {
+ let to_mute = &[
+ // "disabled" on <link> or "autocomplete" on <select> emit this warning
+ "PROPRIETARY_ATTRIBUTE",
+ // It complains when multiple in the same page link to the same anchor for some reason...
+ "ANCHOR_NOT_UNIQUE",
+ // If a <span> contains only HTML elements and no text, it complains about it.
+ "TRIM_EMPTY_ELEMENT",
+ // FIXME: the three next warnings are about <pre> elements which are not supposed to
+ // contain HTML. The solution here would be to replace them with a <div>
+ "MISSING_ENDTAG_BEFORE",
+ "INSERTING_TAG",
+ "DISCARDING_UNEXPECTED",
+ // This error is caused by nesting the Notable Traits tooltip within an <h4> tag.
+ // The solution is to avoid doing that, but we need to have the <h4> tags for accessibility
+ // reasons, and we need the Notable Traits tooltip to help everyone understand the Iterator
+ // combinators
+ "TAG_NOT_ALLOWED_IN",
+ ];
+ let to_mute_s = to_mute.join(",");
+ let mut command = Command::new("tidy");
+ command
+ .arg("-errors")
+ .arg("-quiet")
+ .arg("--mute-id") // this option is useful in case we want to mute more warnings
+ .arg("yes")
+ .arg("--mute")
+ .arg(&to_mute_s)
+ .arg(file);
+
+ let Output { status, stderr, .. } = command.output().expect("failed to run tidy command");
+ if status.success() {
+ 0
+ } else {
+ let stderr = String::from_utf8(stderr).expect("String::from_utf8 failed...");
+ if stderr.is_empty() && status.code() != Some(2) {
+ 0
+ } else {
+ eprintln!(
+ "=> Errors for `{}` (error code: {}) <=",
+ file.display(),
+ status.code().unwrap_or(-1)
+ );
+ eprintln!("{}", stderr);
+ stderr.lines().count()
+ }
+ }
+}
+
+const DOCS_TO_CHECK: &[&str] =
+ &["alloc", "core", "proc_macro", "implementors", "src", "std", "test"];
+
+// Returns the number of files read and the number of errors.
+fn find_all_html_files(dir: &Path) -> (usize, usize) {
+ walkdir::WalkDir::new(dir)
+ .into_iter()
+ .filter_entry(|e| {
+ e.depth() != 1
+ || e.file_name()
+ .to_str()
+ .map(|s| DOCS_TO_CHECK.into_iter().any(|d| *d == s))
+ .unwrap_or(false)
+ })
+ .par_bridge()
+ .map(|entry| {
+ let entry = entry.expect("failed to read file");
+ if !entry.file_type().is_file() {
+ return (0, 0);
+ }
+ let entry = entry.path();
+ // (Number of files processed, number of errors)
+ if entry.extension().and_then(|s| s.to_str()) == Some("html") {
+ (1, check_html_file(&entry))
+ } else {
+ (0, 0)
+ }
+ })
+ .reduce(|| (0, 0), |a, b| (a.0 + b.0, a.1 + b.1))
+}
+
+/// Default `tidy` command for macOS is too old that it does not have `mute-id` and `mute` options.
+/// `tidy` on macOS Monterey was released on 31 October 2006, and the same date can be seen seven
+/// years ago at <https://stackoverflow.com/questions/22283382/overwrite-osx-tidy>. Accordingly,
+/// the macOS environment using pre-installed `tidy` should immediately suspend HTML checker process
+/// and show a hint to install a newer one.
+#[cfg(target_os = "macos")]
+fn check_tidy_version() -> Result<(), String> {
+ let output = Command::new("tidy").arg("-v").output().expect("failed to run tidy command");
+ let version = String::from_utf8(output.stdout).expect("failed to read version of tidy command");
+ if version.contains("HTML Tidy for Mac OS X released on 31 October 2006") {
+ eprintln!("The pre-installed HTML Tidy for macOS is not supported.");
+ eprintln!("Consider installing a newer one and re-running.");
+ eprintln!("If you're using Homebrew, you can install it by the following command:");
+ eprintln!(" brew install tidy-html5");
+ eprintln!();
+ Err("HTML check failed: 1 error".to_string())
+ } else {
+ Ok(())
+ }
+}
+
+fn main() -> Result<(), String> {
+ let args = env::args().collect::<Vec<_>>();
+ if args.len() != 2 {
+ return Err(format!("Usage: {} <doc folder>", args[0]));
+ }
+ #[cfg(target_os = "macos")]
+ check_tidy_version()?;
+
+ println!("Running HTML checker...");
+
+ let (files_read, errors) = find_all_html_files(&Path::new(&args[1]));
+ println!("Done! Read {} files...", files_read);
+ if errors > 0 {
+ Err(format!("HTML check failed: {} errors", errors))
+ } else {
+ println!("No error found!");
+ Ok(())
+ }
+}