Add minify support (#1146)
* Doc add a missing arg to `get_taxonomy_url` (#1139) This feature is already exist, but not in the doc yet Related #766 * Add minify support * Add documentation * Code review * Fix error in documentation * Update minify-html to 0.3.6 * Move minify into write_content function * Fix multiple calls to minify() * Add test for minified output * Fix breaking test Co-authored-by: Ken <2770219+ken0x0a@users.noreply.github.com>
This commit is contained in:
parent
d571dea8c3
commit
0df3631b3d
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -1320,6 +1320,17 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minify-html"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b917ef1eb405ca3b1a489608f36392f0718ff4740bbc6f7d89edd4ec4c869fb7"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.3.7"
|
||||
|
@ -2177,6 +2188,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"library",
|
||||
"link_checker",
|
||||
"minify-html",
|
||||
"rayon",
|
||||
"sass-rs",
|
||||
"search",
|
||||
|
|
|
@ -74,6 +74,8 @@ pub struct Config {
|
|||
|
||||
/// Whether to compile the `sass` directory and output the css files into the static folder
|
||||
pub compile_sass: bool,
|
||||
/// Whether to minify the html output
|
||||
pub minify_html: bool,
|
||||
/// Whether to build the search index for the content
|
||||
pub build_search_index: bool,
|
||||
/// A list of file glob patterns to ignore when processing the content folder. Defaults to none.
|
||||
|
@ -320,6 +322,7 @@ impl Default for Config {
|
|||
hard_link_static: false,
|
||||
taxonomies: Vec::new(),
|
||||
compile_sass: false,
|
||||
minify_html: false,
|
||||
mode: Mode::Build,
|
||||
build_search_index: false,
|
||||
ignored_content: Vec::new(),
|
||||
|
|
|
@ -8,6 +8,7 @@ include = ["src/**/*"]
|
|||
[dependencies]
|
||||
tera = "1"
|
||||
glob = "0.3"
|
||||
minify-html = "0.3.6"
|
||||
rayon = "1"
|
||||
serde = "1"
|
||||
serde_derive = "1"
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::sync::{Arc, Mutex, RwLock};
|
|||
|
||||
use glob::glob;
|
||||
use lazy_static::lazy_static;
|
||||
use minify_html::{truncate, Cfg};
|
||||
use rayon::prelude::*;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
|
@ -445,6 +446,21 @@ impl Site {
|
|||
html
|
||||
}
|
||||
|
||||
/// Minifies html content
|
||||
fn minify(&self, html: String) -> Result<String> {
|
||||
let cfg = &Cfg { minify_js: false };
|
||||
let mut input_bytes = html.as_bytes().to_vec();
|
||||
match truncate(&mut input_bytes, cfg) {
|
||||
Ok(_len) => match std::str::from_utf8(&mut input_bytes) {
|
||||
Ok(result) => Ok(result.to_string()),
|
||||
Err(err) => bail!("Failed to convert bytes to string : {}", err),
|
||||
},
|
||||
Err(minify_error) => {
|
||||
bail!("Failed to truncate html at character {}:", minify_error.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Copy the main `static` folder and the theme `static` folder if a theme is used
|
||||
pub fn copy_static_directories(&self) -> Result<()> {
|
||||
// The user files will overwrite the theme files
|
||||
|
@ -511,10 +527,19 @@ impl Site {
|
|||
create_directory(¤t_path)?;
|
||||
}
|
||||
|
||||
let final_content = if !filename.ends_with("html") || !self.config.minify_html {
|
||||
content
|
||||
} else {
|
||||
match self.minify(content) {
|
||||
Ok(minified_content) => minified_content,
|
||||
Err(error) => bail!(error),
|
||||
}
|
||||
};
|
||||
|
||||
match self.build_mode {
|
||||
BuildMode::Disk => {
|
||||
let end_path = current_path.join(filename);
|
||||
create_file(&end_path, &content)?;
|
||||
create_file(&end_path, &final_content)?;
|
||||
}
|
||||
BuildMode::Memory => {
|
||||
let path = if filename != "index.html" {
|
||||
|
@ -527,7 +552,7 @@ impl Site {
|
|||
}
|
||||
.trim_end_matches('/')
|
||||
.to_owned();
|
||||
&SITE_CONTENT.write().unwrap().insert(path, content);
|
||||
&SITE_CONTENT.write().unwrap().insert(path, final_content);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -543,8 +568,12 @@ impl Site {
|
|||
let output = page.render_html(&self.tera, &self.config, &self.library.read().unwrap())?;
|
||||
let content = self.inject_livereload(output);
|
||||
let components: Vec<&str> = page.path.split('/').collect();
|
||||
let current_path =
|
||||
self.write_content(&components, "index.html", content, !page.assets.is_empty())?;
|
||||
let current_path = self.write_content(
|
||||
&components,
|
||||
"index.html",
|
||||
content,
|
||||
!page.assets.is_empty(),
|
||||
)?;
|
||||
|
||||
// Copy any asset we found previously into the same directory as the index.html
|
||||
for asset in &page.assets {
|
||||
|
|
|
@ -712,6 +712,18 @@ fn can_build_site_custom_builtins_from_theme() {
|
|||
assert!(file_contains!(public, "404.html", "Oops"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_build_site_with_html_minified() {
|
||||
let (_, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
|
||||
site.config.minify_html = true;
|
||||
(site, true)
|
||||
});
|
||||
|
||||
assert!(&public.exists());
|
||||
assert!(file_exists!(public, "index.html"));
|
||||
assert!(file_contains!(public, "index.html", "<!DOCTYPE html><html lang=en><head><meta charset=UTF-8>"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_ignore_markdown_content() {
|
||||
let (_, _tmp_dir, public) = build_site("test_site");
|
||||
|
|
|
@ -85,6 +85,9 @@ languages = []
|
|||
# When set to "true", the Sass files in the `sass` directory are compiled.
|
||||
compile_sass = false
|
||||
|
||||
# When set to "true", the HTML output files will be minified
|
||||
minify_html = false
|
||||
|
||||
# A list of glob patterns specifying asset files to ignore when the content
|
||||
# directory is processed. Defaults to none, which means that all asset files are
|
||||
# copied over to the `public` directory.
|
||||
|
|
Loading…
Reference in a new issue