inline js data

This commit is contained in:
Robin Appelman 2023-04-29 17:30:56 +02:00
commit 1e2a3e28e7
8 changed files with 111 additions and 69 deletions

View file

@ -1,6 +1,8 @@
mod script;
mod style;
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use fnv::FnvHasher;
pub use script::bundle_script;
use std::fs::read;
@ -43,3 +45,20 @@ pub fn guess_mime(path: &str) -> &'static str {
}
return "text/plain";
}
fn inline_url(path: &str) -> String {
let content = read(path).unwrap_or_else(|e| {
eprintln!("Failed to write inline file {path}: {e}");
panic!("Failed to inline");
});
let (mime, encode) = guess_embed(path);
if encode {
let encoded = STANDARD.encode(content);
format!("data:{mime};base64,{encoded}")
} else {
let content = String::from_utf8(content).expect("invalid utf8");
let encoded = urlencoding::encode(&content);
format!("data:{mime},{encoded}")
}
}

View file

@ -0,0 +1,39 @@
use crate::inline_url;
use swc_core::ecma::{
ast::*,
visit::{VisitMut, VisitMutWith},
};
pub struct InlineVisitor {}
impl InlineVisitor {
fn visit_require(&mut self, expr: &mut Expr, path: &str) {
if let Some(path) = path.strip_prefix("inline://") {
let data = inline_url(path);
*expr = Expr::Lit(Lit::Str(data.into()));
}
}
}
impl VisitMut for InlineVisitor {
fn visit_mut_expr(&mut self, expr: &mut Expr) {
if let Expr::Call(CallExpr {
args,
callee: Callee::Expr(callee),
..
}) = expr
{
if let Expr::Ident(callee) = callee.as_ref() {
if callee.sym.as_ref() == "require" {
if let Some(arg) = args.first() {
if let Expr::Lit(Lit::Str(arg)) = arg.expr.as_ref() {
let path = arg.value.to_string();
self.visit_require(expr, &path)
}
}
}
}
}
expr.visit_mut_children_with(self);
}
}

View file

@ -1,3 +1,6 @@
mod inline;
use crate::script::inline::InlineVisitor;
use anyhow::Error;
use jsx_dom_expressions::TransformVisitor;
use std::collections::HashMap;
@ -153,6 +156,7 @@ impl Load for Loader {
let module = module
.fold_with(&mut strip(top_level_mark))
.fold_with(&mut as_folder(InlineVisitor {}))
.fold_with(&mut as_folder(TransformVisitor::new(
jsx_dom_expressions::config::Config {
module_name: "solid-js/web".to_string(),

View file

@ -1,6 +1,4 @@
use crate::guess_embed;
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use crate::inline_url;
use lightningcss::bundler::{Bundler, FileProvider};
use lightningcss::stylesheet::{MinifyOptions, ParserOptions, PrinterOptions};
use lightningcss::targets::Browsers;
@ -8,7 +6,6 @@ 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) -> Vec<u8> {
@ -61,20 +58,7 @@ impl<'i> Visitor<'i> for InlineUrlVisitor {
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_embed(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();
}
url.url = inline_url(path).into();
}
Ok(())
}