html5_picture/
lib.rs

1//! ## Purpose
2//!
3//! Supports the binary within this package.
4//! Contains functions to easily generate different sizes of a picture that
5//! can be used on webpages. Also offers the possibility to convert them into webp
6//! format and is able to create `<picture>` tags for the given images.
7//!
8//! Currently this crate is only capable of converting `png` files to webp using
9//! `cwebp`.
10//! So make sure that webp is installed on your computer.
11//!
12//! ## Installation
13//!
14//! The binary can be installed via `cargo install html5-picture`. As stated
15//! before, make sure webp is installed before using.
16//!
17//! ## Usage
18//!
19//! Use `html5-picture --help` for an overview of all parameters.
20//!
21//! ## Examples
22//!
23//! ### Conversion with three scales and 70% quality
24//! If you want to create three different sizes of the images in `./assets`
25//! with a conversion quality of 70%, enter the following command:
26//!
27//! ```bash
28//! html5-picture ./assets 3 -q 70
29//! ```
30//!
31//! This will convert your images and save them to `./assets-html5picture`.
32//! This folder is also the working directory make sure to not modify it while
33//! the application is running.
34//!
35//! ### Conversion with given installation folder
36//! If you pass `-i <folder_name>` as parameter, the resulting files are
37//! moved from the working directory to the given `<folder_name>` after conversion
38//! and scaling.
39//!
40//! ```bash
41//! html5-picture ./assets 3 -q 100 -i ./assets-build
42//! ```
43//!
44//! In this example the images are installted to `./assets-build`.
45//!
46//! ### Force overwriting
47//! Using the `-f` or `--force-overwrite` flag will overwrite existing webp or
48//! HTML5 picture tag files.
49//!
50//! ```bash
51//! html5-picture ./assets 3 -q 100 -i ./dist -f
52//! ```
53//!
54//! ### Writing picture tag files to disk
55//! With the `-p` option, it is possible to save the `<picture>` tags to disk.
56//! However it is recommended to use it in combination with -m, which sets the
57//! mountpoint in your tag files for you.
58//!
59//! ```bash
60//! html5-picture ./assets 4 -i ./dist -p ./html5-tags -m /some/web-server/mountpoint
61//! ```
62//!
63//! ### Read input files by JSON
64//! **Upcoming feature.**
65//! The pictures can be defined using JSON format. `html5-picture` will read it
66//! from stdin. This enables definition of all attributes such as `alt` per image.
67#[deny(missing_docs)]
68#[deny(rustdoc::missing_crate_level_docs)]
69#[deny(rustdoc::broken_intra_doc_links)]
70#[deny(rustdoc::private_intra_doc_links)]
71use {
72    crate::core::{
73        Config, State, collect_file_names, copy_originals_to_output,
74        create_all_output_directories, install_images_into, process_images,
75        save_html_picture_tags,
76    },
77    indicatif::ProgressBar,
78    log::error,
79    queue::Queue,
80    std::path::PathBuf,
81    walkdir::WalkDir,
82};
83
84/// Contains default functions and traits.
85pub mod core;
86
87/// Generic helper functions.
88pub mod utils;
89
90/// Support for webp format. Used mainly for conversion.
91pub mod webp;
92
93/// Path processing that is required for ```html5_picture```
94pub mod path;
95
96/// Functions operating on the filesystem that is required for ```html5_picture```
97pub mod fs;
98
99/// HTML5 related functions, such as creation of picture tags.
100pub mod html5;
101
102/// Determines if the given input filename contains a .png extension.
103pub fn is_png(input: &PathBuf) -> bool {
104    match input.extension() {
105        Some(s) => match s.to_str() {
106            None => false,
107            Some(v) => v == "png",
108        },
109        None => false,
110    }
111}
112
113/// Collects all png file names that are stored in the ```input_dir```.
114pub fn collect_png_file_names(
115    input_dir: &PathBuf,
116    progressbar: Option<ProgressBar>,
117) -> Vec<PathBuf> {
118    let mut file_names = vec![];
119    for entry in WalkDir::new(&input_dir) {
120        // unwrap the entry
121        let entry = if let Err(msg) = &entry {
122            error!("{}", msg.to_string());
123            continue;
124        } else {
125            entry.unwrap()
126        };
127        let entry = entry.into_path();
128
129        if let Some(ref pb) = progressbar {
130            pb.tick();
131        }
132
133        if !is_png(&entry) {
134            continue;
135        }
136        file_names.push(entry);
137    }
138    file_names
139}
140
141/// The main function of the binary. Executes all required steps for copying,
142/// conversion and installationn of the source images.
143pub fn run(config: Config) {
144    if !&config.input_dir.exists() {
145        error!("Input directory does not exist!");
146        return;
147    }
148    match &config.scaled_images_count {
149        0 => {
150            error!("Minimum scaled images count is 1!");
151            return;
152        }
153        _ => (),
154    }
155
156    // add all default processes
157    let mut q: Queue<fn(&mut State)> = Queue::new();
158    q.queue(collect_file_names).unwrap();
159    q.queue(create_all_output_directories).unwrap();
160    q.queue(copy_originals_to_output).unwrap();
161
162    // finally add processing step
163    q.queue(process_images).unwrap();
164
165    // optional steps
166    if let Some(_) = &config.install_images_into {
167        q.queue(install_images_into).unwrap();
168    }
169    if let Some(_) = &config.picture_tags_output_folder {
170        q.queue(save_html_picture_tags).unwrap();
171    }
172
173    let mut s = State::new(config, q.len());
174
175    while let Some(step_function) = s.dequeue(&mut q) {
176        step_function(&mut s);
177    }
178}