mirror of
https://codeberg.org/demostf/frontend.git
synced 2026-06-03 18:24:12 +02:00
build rework
This commit is contained in:
parent
fc5cd1d24f
commit
dc80d715a6
18 changed files with 1681 additions and 115 deletions
28
build/src/lib.rs
Normal file
28
build/src/lib.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
mod style;
|
||||
|
||||
use const_fnv1a_hash::fnv1a_hash_str_32;
|
||||
pub use style::bundle_style;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! save_asset {
|
||||
($name:expr, $val:expr) => {
|
||||
let val = $val;
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
std::fs::write(format!("{out_dir}/{}", $name), &val).expect("failed to write asset");
|
||||
let hash = fnv1a_hash_str_32(&val);
|
||||
std::fs::write(format!("{out_dir}/{}.hash", $name), format!("{:x}", hash))
|
||||
.expect("failed to write asset hash");
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hash(data: &str) -> String {
|
||||
format!("{:x}", fnv1a_hash_str_32(data))
|
||||
}
|
||||
|
||||
fn guess_mime(path: &str) -> (&'static str, bool) {
|
||||
match path.split('.').last().unwrap() {
|
||||
"svg" => ("image/svg+xml", false),
|
||||
"png" => ("image/png", true),
|
||||
ext => panic!("no mimetype known for {ext}"),
|
||||
}
|
||||
}
|
||||
80
build/src/style.rs
Normal file
80
build/src/style.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use crate::guess_mime;
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use base64::Engine;
|
||||
use lightningcss::bundler::{Bundler, FileProvider};
|
||||
use lightningcss::stylesheet::{MinifyOptions, ParserOptions, PrinterOptions};
|
||||
use lightningcss::targets::Browsers;
|
||||
use lightningcss::values::url::Url;
|
||||
use lightningcss::visit_types;
|
||||
use lightningcss::visitor::{Visit, VisitTypes, Visitor};
|
||||
use std::convert::Infallible;
|
||||
use std::fs::read;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn bundle_style(style: &str) -> String {
|
||||
// todo build time?
|
||||
let fs = FileProvider::new();
|
||||
let mut bundler = Bundler::new(
|
||||
&fs,
|
||||
None,
|
||||
ParserOptions {
|
||||
nesting: true,
|
||||
..ParserOptions::default()
|
||||
},
|
||||
);
|
||||
let mut stylesheet = bundler
|
||||
.bundle(Path::new(style))
|
||||
.expect("failed to bundle css");
|
||||
let browsers =
|
||||
Browsers::from_browserslist(["last 2 versions"]).expect("failed to parse browserlist");
|
||||
stylesheet
|
||||
.minify(MinifyOptions {
|
||||
targets: browsers.clone(),
|
||||
..MinifyOptions::default()
|
||||
})
|
||||
.expect("failed to minify css");
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let minify = false;
|
||||
#[cfg(not(debug_assertions))]
|
||||
let minify = true;
|
||||
|
||||
stylesheet.visit(&mut InlineUrlVisitor).unwrap();
|
||||
|
||||
stylesheet
|
||||
.to_css(PrinterOptions {
|
||||
targets: browsers,
|
||||
minify,
|
||||
..PrinterOptions::default()
|
||||
})
|
||||
.expect("failed to output css")
|
||||
.code
|
||||
}
|
||||
|
||||
struct InlineUrlVisitor;
|
||||
|
||||
impl<'i> Visitor<'i> for InlineUrlVisitor {
|
||||
type Error = Infallible;
|
||||
|
||||
const TYPES: VisitTypes = visit_types!(URLS);
|
||||
|
||||
fn visit_url(&mut self, url: &mut Url<'i>) -> Result<(), Self::Error> {
|
||||
if let Some(path) = url.url.strip_prefix("inline://") {
|
||||
let content = read(path).unwrap_or_else(|e| {
|
||||
eprintln!("Failed to write inline file {path}: {e}");
|
||||
panic!("Failed to inline");
|
||||
});
|
||||
let (mime, encode) = guess_mime(path);
|
||||
|
||||
if encode {
|
||||
let encoded = STANDARD.encode(content);
|
||||
url.url = format!("data:{mime};base64,{encoded}").into();
|
||||
} else {
|
||||
let content = String::from_utf8(content).expect("invalid utf8");
|
||||
let encoded = urlencoding::encode(&content);
|
||||
url.url = format!("data:{mime},{encoded}").into();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue