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}