1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-03-24 07:21:05 +02:00
michael-kerscher 355d65b3ba
Add mdbook-slide-evaluator (#2258)
I created a first implementation for the mdbook-slide-evaluator I
described in #2234.

One has to run a WebDriver compatible browser (e.g. selenium-chromium)
so the slides can be rendered. The browser can access the file either
via a file:// or http:// uri.

The tool grabs the configurable element from that page and evaluates the
size of this element. Output can be stored in a csv file or at stdout
and looks like this at the moment:
```
$ mdbook-slide-evaluator book/html/android/aidl
book/html/android/aidl/birthday-service.html: 750x134
book/html/android/aidl/example-service/changing-definition.html: 750x555
book/html/android/aidl/example-service/changing-implementation.html: 750x786
book/html/android/aidl/example-service/client.html: 750x1096
book/html/android/aidl/example-service/deploy.html: 750x635
book/html/android/aidl/example-service/interface.html: 750x570
book/html/android/aidl/example-service/server.html: 750x837
book/html/android/aidl/example-service/service-bindings.html: 750x483
book/html/android/aidl/example-service/service.html: 750x711
book/html/android/aidl/types/arrays.html: 750x291
book/html/android/aidl/types/file-descriptor.html: 750x1114
book/html/android/aidl/types/objects.html: 750x1258
book/html/android/aidl/types/parcelables.html: 750x637
book/html/android/aidl/types/primitives.html: 750x366
book/html/android/aidl/types.html: 750x197
```

---------

Co-authored-by: Martin Geisler <martin@geisler.net>
2024-08-21 07:18:07 +00:00

123 lines
4.1 KiB
Rust

// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::path::PathBuf;
use clap::Parser;
use log::{debug, info};
use mdbook_slide_evaluator::evaluator::{Evaluator, SlidePolicy};
use mdbook_slide_evaluator::slides::Book;
use tokio_util::sync::CancellationToken;
use url::Url;
#[derive(Parser)]
#[command(version, about, arg_required_else_help(true))]
struct Args {
/// the URI of the webdriver
#[arg(long, default_value_t=String::from("http://localhost:4444"))]
webdriver: String,
/// the XPath to element that is evaluated
#[arg(long, default_value_t=String::from(r#"//*[@id="content"]/main"#))]
element: String,
/// take screenshots of the content element if provided
#[arg(short, long)]
screenshot_dir: Option<PathBuf>,
/// a base url that is used to render the files (relative to source_dir).
/// if you mount the slides at source_dir into / in a webdriver docker
/// container you can use the default
#[arg(long, default_value_t=Url::parse("file:///").unwrap())]
base_url: Url,
/// exports to csv file if provided, otherwise to stdout
#[arg(long)]
export: Option<PathBuf>,
/// allows overwriting the export file
#[arg(long, default_value_t = false)]
overwrite: bool,
/// the height of the webclient that renders the slide
#[arg(long, default_value_t = 1920)]
webclient_width: u32,
/// the width of the webclient that renders the slide
#[arg(long, default_value_t = 1080)]
webclient_height: u32,
/// max width of a slide
#[arg(long, default_value_t = 750)]
width: usize,
/// max height of a slide - default height/width values have 16/9 ratio
#[arg(long, default_value_t = 1333)]
height: usize,
/// if set only violating slides are shown
#[arg(long, default_value_t = false)]
violations_only: bool,
/// directory of the book that is evaluated
source_dir: PathBuf,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// pretty env receives log level from RUST_LOG env variable
pretty_env_logger::init();
let args = Args::parse();
// gather information about the book from the filesystem
let book = Book::from_html_slides(args.source_dir.clone())?;
// create a new webclient that is used by the evaluator
let webclient: fantoccini::Client =
fantoccini::ClientBuilder::native().connect(&args.webdriver).await?;
// use a defined window size for reproducible results
webclient.set_window_size(args.webclient_width, args.webclient_height).await?;
let cancellation_token = CancellationToken::new();
let slide_policy =
SlidePolicy { max_width: args.width, max_height: args.height };
// create a new evaluator (connects to the provided webdriver)
let evaluator = Evaluator::new(
webclient.clone(),
&args.element,
args.screenshot_dir,
args.base_url,
args.source_dir.to_path_buf(),
cancellation_token.clone(),
slide_policy,
);
tokio::spawn(async move {
tokio::signal::ctrl_c().await.unwrap();
info!("received CTRL+C");
// send a cancel signal
cancellation_token.cancel();
});
// evaluate each slide
let score_results = evaluator.eval_book(book).await?;
if let Some(export_file) = args.export {
score_results.export_csv(
&export_file,
args.overwrite,
args.violations_only,
)?;
} else {
score_results.export_stdout(args.violations_only);
}
// close webclient as otherwise the unclosed session cannot be reused
debug!("closing webclient");
webclient.close().await?;
Ok(())
}