Skip to content

Commit

Permalink
inject site config during Sass compilation
Browse files Browse the repository at this point in the history
it is helpful to be able to use site config during Sass compilation,
for example to allow a site owner to set header color in a Sass
template.  in this change we serialize a subset of the site's config
to a `.scss` file as a Sass map literal, allowing config content to
be referenced in site Sass or theme Sass.
  • Loading branch information
greenwoodcm committed Jul 7, 2023
1 parent 2cf0061 commit e73aead
Show file tree
Hide file tree
Showing 8 changed files with 554 additions and 13 deletions.
15 changes: 15 additions & 0 deletions components/config/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ pub struct SerializedConfig<'a> {
markdown: &'a markup::Markdown,
}

#[derive(Serialize)]
pub struct SassConfig<'a> {
base_url: &'a str,
theme: &'a Option<String>,
extra: &'a HashMap<String, Toml>,
}

impl Config {
// any extra syntax and highlight themes have been loaded and validated already by the from_file method before parsing the config
/// Parses a string containing TOML to our Config struct
Expand Down Expand Up @@ -333,6 +340,14 @@ impl Config {
markdown: &self.markdown,
}
}

pub fn sass_config(&self) -> SassConfig {
SassConfig {
base_url: &self.base_url,
theme: &self.theme,
extra: &self.extra,
}
}
}

// merge TOML data that can be a table, or anything else
Expand Down
2 changes: 1 addition & 1 deletion components/site/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ include = ["src/**/*"]

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tempfile = "3"

errors = { path = "../errors" }
config = { path = "../config" }
Expand All @@ -20,5 +21,4 @@ libs = { path = "../libs" }
content = { path = "../content" }

[dev-dependencies]
tempfile = "3"
path-slash = "0.2"
4 changes: 2 additions & 2 deletions components/site/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,13 +708,13 @@ impl Site {
if let Some(ref theme) = self.config.theme {
let theme_path = self.base_path.join("themes").join(theme);
if theme_path.join("sass").exists() {
sass::compile_sass(&theme_path, &self.output_path)?;
sass::compile_sass(&theme_path, &self.output_path, &self.config)?;
start = log_time(start, "Compiled theme Sass");
}
}

if self.config.compile_sass {
sass::compile_sass(&self.base_path, &self.output_path)?;
sass::compile_sass(&self.base_path, &self.output_path, &self.config)?;
start = log_time(start, "Compiled own Sass");
}

Expand Down
42 changes: 34 additions & 8 deletions components/site/src/sass/mod.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
use std::fs::create_dir_all;
use std::path::{Path, PathBuf};

use config::Config;
use libs::globset::Glob;
use libs::grass::{from_path as compile_file, Options, OutputStyle};
use libs::walkdir::{DirEntry, WalkDir};
use tempfile::{tempdir, TempDir};

use crate::anyhow;
use errors::{bail, Result};
use errors::{bail, Result, Context};
use utils::fs::{create_file, ensure_directory_exists};

pub fn compile_sass(base_path: &Path, output_path: &Path) -> Result<()> {
mod serde;

pub fn compile_sass(base_path: &Path, output_path: &Path, config: &Config) -> Result<()> {
ensure_directory_exists(output_path)?;

let sass_path = {
let mut sass_path = PathBuf::from(base_path);
sass_path.push("sass");
sass_path
};
let sass_path = PathBuf::from(base_path).join("sass");

let dependencies_dir = build_dependencies_dir_from_config(config)?;

let options = Options::default().style(OutputStyle::Compressed);
let options = Options::default()
.style(OutputStyle::Compressed)
.load_path(dependencies_dir.path());
let files = get_non_partial_scss(&sass_path);
let mut compiled_paths = Vec::new();

Expand Down Expand Up @@ -52,6 +56,28 @@ pub fn compile_sass(base_path: &Path, output_path: &Path) -> Result<()> {
Ok(())
}

/// write out a subset of the Zola config document to a temporary SCSS file
/// as an SCSS map variable literal. this will allow parts of the site's
/// config to be usable during Sass compilation. this enables theme configuration
/// like allowing the site owner to change header color. this function returns
/// a tempdir holding a single `.scss` file. the tempdir should then be used as
/// a load directory above when compiling the site's Sass files. the tempdir
/// and contained `.scss` file will be deleted on drop of the returned `TempDir`
/// struct, which should happen after Sass compilation finishes.
fn build_dependencies_dir_from_config(config: &Config) -> Result<TempDir> {
let dir = tempdir()
.context("failed to create tempdir for SASS dependencies")?;

let config_serialized = serde::serialize_config(config)?;

std::fs::write(
dir.path().join("zola.scss"),
format!("$config: {}", config_serialized),
)?;

Ok(dir)
}

fn is_partial_scss(entry: &DirEntry) -> bool {
entry.file_name().to_str().map(|s| s.starts_with('_')).unwrap_or(false)
}
Expand Down

0 comments on commit e73aead

Please sign in to comment.