Minify html

This commit is contained in:
asonix 2020-12-14 14:23:02 -06:00
parent 3153eec1de
commit a0cad136f4
4 changed files with 99 additions and 61 deletions

12
Cargo.lock generated
View file

@ -1147,6 +1147,17 @@ version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "minify-html"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ac7185726f6e49b3a692680c54aeee49027351696a2db1bcebafdc33d077e3"
dependencies = [
"aho-corasick",
"lazy_static",
"memchr",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.3" version = "0.4.3"
@ -1343,6 +1354,7 @@ dependencies = [
"env_logger", "env_logger",
"futures", "futures",
"mime", "mime",
"minify-html",
"ructe", "ructe",
"serde", "serde",
"serde_json", "serde_json",

View file

@ -14,6 +14,7 @@ bcrypt = "0.9"
env_logger = "0.8.2" env_logger = "0.8.2"
futures = "0.3" futures = "0.3"
mime = "0.3" mime = "0.3"
minify-html = "0.3.9"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
sled = { version = "0.34.6", features = ["zstd"] } sled = { version = "0.34.6", features = ["zstd"] }

View file

@ -1,5 +1,6 @@
use actix_web::{ use actix_web::{
client::Client, client::Client,
dev::HttpResponseBuilder,
http::{ http::{
header::{CacheControl, CacheDirective, ContentType, LastModified, LOCATION}, header::{CacheControl, CacheDirective, ContentType, LastModified, LOCATION},
StatusCode, StatusCode,
@ -262,13 +263,11 @@ async fn static_files(filename: web::Path<String>, state: web::Data<State>) -> H
} }
async fn not_found(state: web::Data<State>) -> Result<HttpResponse, StateError> { async fn not_found(state: web::Data<State>) -> Result<HttpResponse, StateError> {
let mut cursor = Cursor::new(vec![]); rendered(
|cursor| self::templates::not_found(cursor, &state),
self::templates::not_found(&mut cursor, &state).stateful(&state)?; HttpResponse::NotFound(),
)
Ok(HttpResponse::NotFound() .stateful(&state)
.content_type(mime::TEXT_HTML.essence_str())
.body(cursor.into_inner()))
} }
struct StateError { struct StateError {
@ -296,11 +295,11 @@ impl ResponseError for StateError {
} }
fn error_response(&self) -> HttpResponse { fn error_response(&self) -> HttpResponse {
let mut cursor = Cursor::new(vec![]); match rendered(
match self::templates::error(&mut cursor, &self.error.to_string(), &self.state) { |cursor| self::templates::error(cursor, &self.error.to_string(), &self.state),
Ok(_) => HttpResponse::build(self.status_code()) HttpResponse::build(self.status_code()),
.content_type(mime::TEXT_HTML.essence_str()) ) {
.body(cursor.into_inner()), Ok(res) => res,
Err(_) => HttpResponse::build(self.status_code()) Err(_) => HttpResponse::build(self.status_code())
.content_type(mime::TEXT_PLAIN.essence_str()) .content_type(mime::TEXT_PLAIN.essence_str())
.body(self.error.to_string()), .body(self.error.to_string()),
@ -321,6 +320,15 @@ enum Error {
#[error("{0}")] #[error("{0}")]
UploadString(String), UploadString(String),
#[error("Failed to minify html, {0}")]
Minify(String),
}
impl From<minify_html::Error> for Error {
fn from(e: minify_html::Error) -> Self {
Error::Minify(format!("{:?}", e))
}
} }
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
@ -479,13 +487,11 @@ async fn thumbnail(
} }
async fn index(state: web::Data<State>) -> Result<HttpResponse, StateError> { async fn index(state: web::Data<State>) -> Result<HttpResponse, StateError> {
let mut cursor = Cursor::new(vec![]); rendered(
|cursor| self::templates::index(cursor, &state),
self::templates::index(&mut cursor, &state).stateful(&state)?; HttpResponse::Ok(),
)
Ok(HttpResponse::Ok() .stateful(&state)
.content_type(mime::TEXT_HTML.essence_str())
.body(cursor.into_inner()))
} }
async fn collection( async fn collection(
@ -511,13 +517,12 @@ async fn view_collection(
}; };
let entries = state.store.entries(path.entry_range()).await?; let entries = state.store.entries(path.entry_range()).await?;
let mut cursor = Cursor::new(vec![]); rendered(
|cursor| {
self::templates::view_collection(&mut cursor, path.collection, &collection, &entries, &state)?; self::templates::view_collection(cursor, path.collection, &collection, &entries, &state)
},
Ok(HttpResponse::Ok() HttpResponse::Ok(),
.content_type(mime::TEXT_HTML.essence_str()) )
.body(cursor.into_inner()))
} }
async fn edit_collection( async fn edit_collection(
@ -531,20 +536,19 @@ async fn edit_collection(
}; };
let entries = state.store.entries(path.entry_range()).await?; let entries = state.store.entries(path.entry_range()).await?;
let mut cursor = Cursor::new(vec![]); rendered(
|cursor| {
self::templates::edit_collection( self::templates::edit_collection(
&mut cursor, cursor,
&collection, &collection,
path.collection, path.collection,
&entries, &entries,
&token, &token,
&state, &state,
)?; )
},
Ok(HttpResponse::Ok() HttpResponse::Ok(),
.content_type(mime::TEXT_HTML.essence_str()) )
.body(cursor.into_inner()))
} }
async fn create_collection( async fn create_collection(
@ -629,20 +633,20 @@ async fn delete_entry(
}; };
if !query.confirmed.unwrap_or(false) { if !query.confirmed.unwrap_or(false) {
let mut cursor = Cursor::new(vec![]); return rendered(
self::templates::confirm_entry_delete( |cursor| {
&mut cursor, self::templates::confirm_entry_delete(
entry_path.collection, cursor,
entry_path.entry, entry_path.collection,
&entry, entry_path.entry,
&token, &entry,
&state, &token,
&state,
)
},
HttpResponse::Ok(),
) )
.stateful(&state)?; .stateful(&state);
return Ok(HttpResponse::Ok()
.content_type(mime::TEXT_HTML.essence_str())
.body(cursor.into_inner()));
} }
conn.delete(&entry.filename, &entry.delete_token) conn.delete(&entry.filename, &entry.delete_token)
@ -674,13 +678,19 @@ async fn delete_collection(
None => return Ok(to_404(&state)), None => return Ok(to_404(&state)),
}; };
let mut cursor = Cursor::new(vec![]); return rendered(
self::templates::confirm_delete(&mut cursor, path.collection, &collection, &token, &state) |cursor| {
.stateful(&state)?; self::templates::confirm_delete(
cursor,
return Ok(HttpResponse::Ok() path.collection,
.content_type(mime::TEXT_HTML.essence_str()) &collection,
.body(cursor.into_inner())); &token,
&state,
)
},
HttpResponse::Ok(),
)
.stateful(&state);
} }
let entries = state let entries = state
@ -713,3 +723,18 @@ async fn delete_collection(
Ok(to_home(&state)) Ok(to_home(&state))
} }
fn rendered(
f: impl FnOnce(&mut Cursor<Vec<u8>>) -> std::io::Result<()>,
mut builder: HttpResponseBuilder,
) -> Result<HttpResponse, Error> {
let mut cursor = Cursor::new(vec![]);
(f)(&mut cursor)?;
let mut html = cursor.into_inner();
let len = minify_html::in_place(&mut html, &minify_html::Cfg { minify_js: true })?;
html.truncate(len);
Ok(builder
.content_type(mime::TEXT_HTML.essence_str())
.body(html))
}

View file

@ -17,7 +17,7 @@
<div class="content-group"> <div class="content-group">
<div class="button-group"> <div class="button-group">
@:button("Create Collection", ButtonKind::Submit) @:button("Create Collection", ButtonKind::Submit)
</button> </div>
</div> </div>
</form> </form>
</article> </article>