Skip to content

Commit

Permalink
Feat: Manganis SCSS Support (#3294)
Browse files Browse the repository at this point in the history
* feat: scss manganis support

* revision: make ScssLogger private
  • Loading branch information
DogeDark authored Dec 5, 2024
1 parent e6f76c7 commit bff5478
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 1 deletion.
42 changes: 42 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions packages/cli-opt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ image = { version = "0.25", features = ["avif"] }
# CSS Minification
lightningcss = "1.0.0-alpha.60"

# SCSS Processing
grass = "0.13.4"
codemap = "0.1.3"

# Js minification - swc has introduces minor versions with breaking changes in the past so we pin all of their crates
swc = "=0.283.0"
swc_allocator = { version = "=0.1.8", default-features = false }
Expand Down
57 changes: 57 additions & 0 deletions packages/cli-opt/src/css.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::path::Path;

use anyhow::Context;
use codemap::SpanLoc;
use grass::OutputStyle;
use lightningcss::{
printer::PrinterOptions,
stylesheet::{MinifyOptions, ParserOptions, StyleSheet},
};
use manganis_core::CssAssetOptions;
use tracing::{debug, warn};

pub(crate) fn process_css(
css_options: &CssAssetOptions,
Expand Down Expand Up @@ -40,3 +43,57 @@ pub(crate) fn minify_css(css: &str) -> String {
let res = stylesheet.to_css(printer).unwrap();
res.code
}

/// Process an scss/sass file into css.
pub(crate) fn process_scss(
scss_options: &CssAssetOptions,
source: &Path,
output_path: &Path,
) -> anyhow::Result<()> {
let style = match scss_options.minified() {
true => OutputStyle::Compressed,
false => OutputStyle::Expanded,
};

let options = grass::Options::default()
.style(style)
.quiet(false)
.logger(&ScssLogger {});

let css = grass::from_path(source, &options)?;
let minified = minify_css(&css);

std::fs::write(output_path, minified).with_context(|| {
format!(
"Failed to write css to output location: {}",
output_path.display()
)
})?;

Ok(())
}

/// Logger for Grass that re-uses their StdLogger formatting but with tracing.
#[derive(Debug)]
struct ScssLogger {}

impl grass::Logger for ScssLogger {
fn debug(&self, location: SpanLoc, message: &str) {
debug!(
"{}:{} DEBUG: {}",
location.file.name(),
location.begin.line + 1,
message
);
}

fn warn(&self, location: SpanLoc, message: &str) {
warn!(
"Warning: {}\n ./{}:{}:{}",
message,
location.file.name(),
location.begin.line + 1,
location.begin.column + 1
);
}
}
5 changes: 5 additions & 0 deletions packages/cli-opt/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use anyhow::Context;
use manganis_core::{AssetOptions, CssAssetOptions, ImageAssetOptions, JsAssetOptions};
use std::path::Path;

use crate::css::process_scss;

use super::{
css::process_css, folder::process_folder, image::process_image, js::process_js,
json::process_json,
Expand Down Expand Up @@ -29,6 +31,9 @@ pub fn process_file_to(
Some("css") => {
process_css(&CssAssetOptions::new(), source, output_path)?;
}
Some("scss" | "sass") => {
process_scss(&CssAssetOptions::new(), source, output_path)?;
}
Some("js") => {
process_js(&JsAssetOptions::new(), source, output_path)?;
}
Expand Down
26 changes: 25 additions & 1 deletion packages/manganis/manganis/src/macro_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,38 @@ pub const fn generate_unique_path(
None => {
if let Some(extension) = extension {
macro_output_path = macro_output_path.push('.');
macro_output_path = macro_output_path.push_str(extension.as_str())

let ext_bytes = extension.as_str().as_bytes();

// Rewrite scss as css
if bytes_equal(ext_bytes, b"scss") || bytes_equal(ext_bytes, b"sass") {
macro_output_path = macro_output_path.push_str("css")
} else {
macro_output_path = macro_output_path.push_str(extension.as_str())
}
}
}
}

macro_output_path
}

const fn bytes_equal(left: &[u8], right: &[u8]) -> bool {
if left.len() != right.len() {
return false;
}

let mut i = 0;
while i < left.len() {
if left[i] != right[i] {
return false;
}
i += 1;
}

true
}

#[test]
fn test_unique_path() {
use manganis_core::{ImageAssetOptions, ImageFormat};
Expand Down

0 comments on commit bff5478

Please sign in to comment.