Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/autofmt/tests/srcless/basic_expr.rsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ parse_quote! {
}
p {
img {
src: asset!("/example-book/assets1/logo.png", ImageAssetOptions::new().with_avif()),
src: asset!("/example-book/assets1/logo.png", AssetOptions::image().with_avif()),
alt: "some_local1",
title: "",
}
img {
src: asset!("/example-book/assets2/logo.png", ImageAssetOptions::new().with_avif()),
src: asset!("/example-book/assets2/logo.png", AssetOptions::image().with_avif()),
alt: "some_local2",
title: "",
}
Expand Down
48 changes: 29 additions & 19 deletions packages/cli-opt/src/file.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Context;
use manganis::{CssModuleAssetOptions, FolderAssetOptions};
use manganis_core::{AssetOptions, CssAssetOptions, ImageAssetOptions, JsAssetOptions};
use manganis::{AssetOptions, CssModuleAssetOptions, FolderAssetOptions};
use manganis_core::{AssetVariant, CssAssetOptions, ImageAssetOptions, JsAssetOptions};
use std::path::Path;

use crate::css::{process_css_module, process_scss};
Expand All @@ -26,10 +26,10 @@ pub(crate) fn process_file_to_with_options(
output_path: &Path,
in_folder: bool,
) -> anyhow::Result<()> {
// If the file already exists, then we must have a file with the same hash
// already. The hash has the file contents and options, so if we find a file
// with the same hash, we probably already created this file in the past
if output_path.exists() {
// If the file already exists and this is a hashed asset, then we must have a file
// with the same hash already. The hash has the file contents and options, so if we
// find a file with the same hash, we probably already created this file in the past
if output_path.exists() && options.hash_suffix() {
return Ok(());
}
if let Some(parent) = output_path.parent() {
Expand All @@ -48,7 +48,7 @@ pub(crate) fn process_file_to_with_options(
.unwrap_or_default()
.to_string_lossy()
));
let resolved_options = resolve_asset_options(source, options);
let resolved_options = resolve_asset_options(source, options.variant());

match &resolved_options {
ResolvedAssetType::Css(options) => {
Expand Down Expand Up @@ -86,6 +86,16 @@ pub(crate) fn process_file_to_with_options(
}
}

// Remove the existing output file if it exists
if output_path.exists() {
if output_path.is_file() {
std::fs::remove_file(output_path).context("Failed to remove previous output file")?;
} else if output_path.is_dir() {
std::fs::remove_dir_all(output_path)
.context("Failed to remove previous output file")?;
}
}

// If everything was successful, rename the temp file to the final output path
std::fs::rename(temp_path, output_path).context("Failed to rename output file")?;

Expand All @@ -111,14 +121,14 @@ pub(crate) enum ResolvedAssetType {
File,
}

pub(crate) fn resolve_asset_options(source: &Path, options: &AssetOptions) -> ResolvedAssetType {
pub(crate) fn resolve_asset_options(source: &Path, options: &AssetVariant) -> ResolvedAssetType {
match options {
AssetOptions::Image(image) => ResolvedAssetType::Image(*image),
AssetOptions::Css(css) => ResolvedAssetType::Css(*css),
AssetOptions::CssModule(css) => ResolvedAssetType::CssModule(*css),
AssetOptions::Js(js) => ResolvedAssetType::Js(*js),
AssetOptions::Folder(folder) => ResolvedAssetType::Folder(*folder),
AssetOptions::Unknown => resolve_unknown_asset_options(source),
AssetVariant::Image(image) => ResolvedAssetType::Image(*image),
AssetVariant::Css(css) => ResolvedAssetType::Css(*css),
AssetVariant::CssModule(css) => ResolvedAssetType::CssModule(*css),
AssetVariant::Js(js) => ResolvedAssetType::Js(*js),
AssetVariant::Folder(folder) => ResolvedAssetType::Folder(*folder),
AssetVariant::Unknown => resolve_unknown_asset_options(source),
_ => {
tracing::warn!("Unknown asset options... you may need to update the Dioxus CLI. Defaulting to a generic file: {:?}", options);
resolve_unknown_asset_options(source)
Expand All @@ -128,14 +138,14 @@ pub(crate) fn resolve_asset_options(source: &Path, options: &AssetOptions) -> Re

fn resolve_unknown_asset_options(source: &Path) -> ResolvedAssetType {
match source.extension().map(|e| e.to_string_lossy()).as_deref() {
Some("scss" | "sass") => ResolvedAssetType::Scss(CssAssetOptions::new()),
Some("css") => ResolvedAssetType::Css(CssAssetOptions::new()),
Some("js") => ResolvedAssetType::Js(JsAssetOptions::new()),
Some("scss" | "sass") => ResolvedAssetType::Scss(CssAssetOptions::default()),
Some("css") => ResolvedAssetType::Css(CssAssetOptions::default()),
Some("js") => ResolvedAssetType::Js(JsAssetOptions::default()),
Some("json") => ResolvedAssetType::Json,
Some("jpg" | "jpeg" | "png" | "webp" | "avif") => {
ResolvedAssetType::Image(ImageAssetOptions::new())
ResolvedAssetType::Image(ImageAssetOptions::default())
}
_ if source.is_dir() => ResolvedAssetType::Folder(FolderAssetOptions::new()),
_ if source.is_dir() => ResolvedAssetType::Folder(FolderAssetOptions::default()),
_ => ResolvedAssetType::File,
}
}
2 changes: 1 addition & 1 deletion packages/cli-opt/src/folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub fn process_folder(source: &Path, output_folder: &Path) -> anyhow::Result<()>
/// Optimize a file without changing any of its contents significantly (e.g. by changing the extension)
fn process_file_minimal(input_path: &Path, output_path: &Path) -> anyhow::Result<()> {
process_file_to_with_options(
&manganis_core::AssetOptions::Unknown,
&manganis_core::AssetOptions::builder().into_asset_options(),
input_path,
output_path,
true,
Expand Down
9 changes: 6 additions & 3 deletions packages/cli-opt/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub(crate) fn hash_file_with_options(
hasher: &mut impl Hasher,
in_folder: bool,
) -> anyhow::Result<()> {
let resolved_options = resolve_asset_options(source, options);
let resolved_options = resolve_asset_options(source, options.variant());

match &resolved_options {
// Scss and JS can import files during the bundling process. We need to hash
Expand Down Expand Up @@ -145,8 +145,11 @@ pub fn add_hash_to_asset(asset: &mut BundledAsset) {
.map(|byte| format!("{byte:x}"))
.collect::<String>();
let file_stem = source_path.file_stem().unwrap_or(file_name);
let mut bundled_path =
PathBuf::from(format!("{}-dxh{hash}", file_stem.to_string_lossy()));
let mut bundled_path = if asset.options().hash_suffix() {
PathBuf::from(format!("{}-dxh{hash}", file_stem.to_string_lossy()))
} else {
PathBuf::from(file_stem)
};

if let Some(ext) = ext {
bundled_path.set_extension(ext);
Expand Down
26 changes: 17 additions & 9 deletions packages/cli/src/build/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@ use dioxus_cli_config::{APP_TITLE_ENV, ASSET_ROOT_ENV};
use dioxus_cli_opt::{process_file_to, AssetManifest};
use itertools::Itertools;
use krates::{cm::TargetKind, NodeId};
use manganis::{AssetOptions, JsAssetOptions};
use manganis::AssetOptions;
use manganis_core::AssetVariant;
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
use serde::{Deserialize, Serialize};
use std::{
Expand Down Expand Up @@ -3283,7 +3284,7 @@ impl BuildRequest {
writeln!(
glue, "export const __wasm_split_load_chunk_{idx} = makeLoad(\"/assets/{url}\", [], fusedImports);",
url = assets
.register_asset(&path, AssetOptions::Unknown)?.bundled_path(),
.register_asset(&path, AssetOptions::builder().into_asset_options())?.bundled_path(),
)?;
}

Expand Down Expand Up @@ -3311,7 +3312,8 @@ impl BuildRequest {

// Again, register this wasm with the asset system
url = assets
.register_asset(&path, AssetOptions::Unknown)?.bundled_path(),
.register_asset(&path, AssetOptions::builder().into_asset_options())?
.bundled_path(),

// This time, make sure to write the dependencies of this chunk
// The names here are again, hardcoded in wasm-split - fix this eventually.
Expand Down Expand Up @@ -3359,7 +3361,10 @@ impl BuildRequest {

if self.should_bundle_to_asset() {
// Make sure to register the main wasm file with the asset system
assets.register_asset(&post_bindgen_wasm, AssetOptions::Unknown)?;
assets.register_asset(
&post_bindgen_wasm,
AssetOptions::builder().into_asset_options(),
)?;
}

// Now that the wasm is registered as an asset, we can write the js glue shim
Expand All @@ -3369,7 +3374,10 @@ impl BuildRequest {
// Register the main.js with the asset system so it bundles in the snippets and optimizes
assets.register_asset(
&self.wasm_bindgen_js_output_file(),
AssetOptions::Js(JsAssetOptions::new().with_minify(true).with_preload(true)),
AssetOptions::js()
.with_minify(true)
.with_preload(true)
.into_asset_options(),
)?;
}

Expand Down Expand Up @@ -4007,22 +4015,22 @@ __wbg_init({{module_or_path: "/{}/{wasm_path}"}}).then((wasm) => {{
// Inject any resources from manganis into the head
for asset in assets.assets() {
let asset_path = asset.bundled_path();
match asset.options() {
AssetOptions::Css(css_options) => {
match asset.options().variant() {
AssetVariant::Css(css_options) => {
if css_options.preloaded() {
head_resources.push_str(&format!(
"<link rel=\"preload\" as=\"style\" href=\"/{{base_path}}/assets/{asset_path}\" crossorigin>"
))
}
}
AssetOptions::Image(image_options) => {
AssetVariant::Image(image_options) => {
if image_options.preloaded() {
head_resources.push_str(&format!(
"<link rel=\"preload\" as=\"image\" href=\"/{{base_path}}/assets/{asset_path}\" crossorigin>"
))
}
}
AssetOptions::Js(js_options) => {
AssetVariant::Js(js_options) => {
if js_options.preloaded() {
head_resources.push_str(&format!(
"<link rel=\"preload\" as=\"script\" href=\"/{{base_path}}/assets/{asset_path}\" crossorigin>"
Expand Down
31 changes: 0 additions & 31 deletions packages/manganis/manganis-core/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,37 +66,6 @@ impl BundledAsset {
}
}

#[doc(hidden)]
/// This should only be called from the macro
/// Create a new asset but with a relative path
///
/// This method is deprecated and will be removed in a future release.
#[deprecated(
note = "Relative asset!() paths are not supported. Use a path like `/assets/myfile.png` instead of `./assets/myfile.png`"
)]
pub const fn new_relative(
absolute_source_path: &'static str,
bundled_path: &'static str,
options: AssetOptions,
) -> Self {
Self::new(absolute_source_path, bundled_path, options)
}

#[doc(hidden)]
/// This should only be called from the macro
/// Create a new asset from const paths
pub const fn new_from_const(
absolute_source_path: ConstStr,
bundled_path: ConstStr,
options: AssetOptions,
) -> Self {
Self {
absolute_source_path,
bundled_path,
options,
}
}

/// Get the bundled name of the asset. This identifier cannot be used to read the asset directly
pub fn bundled_path(&self) -> &str {
self.bundled_path.as_str()
Expand Down
67 changes: 45 additions & 22 deletions packages/manganis/manganis-core/src/css.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::AssetOptions;
use crate::{AssetOptions, AssetOptionsBuilder, AssetVariant};
use const_serialize::SerializeConst;

/// Options for a css asset
Expand All @@ -21,35 +21,60 @@ pub struct CssAssetOptions {

impl Default for CssAssetOptions {
fn default() -> Self {
Self::new()
Self::default()
}
}

impl CssAssetOptions {
/// Create a new css asset using the builder
pub const fn new() -> Self {
#[deprecated(note = "Use `AssetOptions::css()` instead", since = "0.7.0")]
pub const fn new() -> AssetOptionsBuilder<CssAssetOptions> {
AssetOptions::css()
}

/// Create a default css asset options
pub const fn default() -> Self {
Self {
preload: false,
minify: true,
}
}

/// Check if the asset is preloaded
pub const fn preloaded(&self) -> bool {
self.preload
}

/// Check if the asset is minified
pub const fn minified(&self) -> bool {
self.minify
}
}

impl AssetOptions {
/// Create a new css asset builder
///
/// ```rust
/// # use manganis::{asset, Asset, CssAssetOptions};
/// const _: Asset = asset!("/assets/style.css", AssetOptions::css());
/// ```
pub const fn css() -> AssetOptionsBuilder<CssAssetOptions> {
AssetOptionsBuilder::variant(CssAssetOptions::default())
}
}

impl AssetOptionsBuilder<CssAssetOptions> {
/// Sets whether the css should be minified (default: true)
///
/// Minifying the css can make your site load faster by loading less data
///
/// ```rust
/// # use manganis::{asset, Asset, CssAssetOptions};
/// const _: Asset = asset!("/assets/style.css", CssAssetOptions::new().with_minify(false));
/// const _: Asset = asset!("/assets/style.css", AssetOptions::css().with_minify(false));
/// ```
#[allow(unused)]
pub const fn with_minify(self, minify: bool) -> Self {
Self { minify, ..self }
}

/// Check if the asset is minified
pub const fn minified(&self) -> bool {
self.minify
pub const fn with_minify(mut self, minify: bool) -> Self {
self.variant.minify = minify;
self
}

/// Make the asset preloaded
Expand All @@ -58,20 +83,18 @@ impl CssAssetOptions {
///
/// ```rust
/// # use manganis::{asset, Asset, CssAssetOptions};
/// const _: Asset = asset!("/assets/style.css", CssAssetOptions::new().with_preload(true));
/// const _: Asset = asset!("/assets/style.css", AssetOptions::css().with_preload(true));
/// ```
#[allow(unused)]
pub const fn with_preload(self, preload: bool) -> Self {
Self { preload, ..self }
}

/// Check if the asset is preloaded
pub const fn preloaded(&self) -> bool {
self.preload
pub const fn with_preload(mut self, preload: bool) -> Self {
self.variant.preload = preload;
self
}

/// Convert the options into options for a generic asset
pub const fn into_asset_options(self) -> AssetOptions {
AssetOptions::Css(self)
AssetOptions {
add_hash: true,
variant: AssetVariant::Css(self.variant),
}
}
}
Loading
Loading