Inject fonts into css

This commit is contained in:
Shadowfacts 2025-01-02 13:15:06 -05:00
parent ec0746011e
commit 0b8717aa2b
8 changed files with 117 additions and 12 deletions

15
Cargo.lock generated
View File

@ -135,6 +135,12 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -624,8 +630,7 @@ dependencies = [
[[package]]
name = "grass"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7a68216437ef68f0738e48d6c7bb9e6e6a92237e001b03d838314b068f33c94"
source = "git+https://git.shadowfacts.net/shadowfacts/grass.git?branch=custom-global-variables#e64e648b6174d23b6d4a8ad674eb443dc6fcbdff"
dependencies = [
"getrandom",
"grass_compiler",
@ -634,14 +639,14 @@ dependencies = [
[[package]]
name = "grass_compiler"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d9e3df7f0222ce5184154973d247c591d9aadc28ce7a73c6cd31100c9facff6"
source = "git+https://git.shadowfacts.net/shadowfacts/grass.git?branch=custom-global-variables#e64e648b6174d23b6d4a8ad674eb443dc6fcbdff"
dependencies = [
"codemap",
"indexmap",
"lasso",
"once_cell",
"phf",
"rand",
]
[[package]]
@ -1891,6 +1896,7 @@ name = "v7"
version = "0.1.0"
dependencies = [
"anyhow",
"base64",
"chrono",
"clap",
"compute_graph",
@ -1898,6 +1904,7 @@ dependencies = [
"env_logger",
"futures",
"grass",
"grass_compiler",
"html5ever",
"log",
"markup5ever_rcdom",

View File

@ -17,13 +17,17 @@ serde_json = "1.0"
[dependencies]
anyhow = "1.0.95"
base64 = "0.22.1"
chrono = { version = "0.4.39", features = ["serde"] }
clap = { version = "4.5.23", features = ["cargo"] }
compute_graph = { path = "crates/compute_graph" }
debounced = "0.2.0"
env_logger = "0.11.6"
futures = "0.3.31"
grass = { version = "0.13.4", default-features = false }
grass = { version = "0.13.4", default-features = false, git = "https://git.shadowfacts.net/shadowfacts/grass.git", branch = "custom-global-variables" }
grass_compiler = { version = "0.13.4", features = [
"custom-builtin-fns",
], git = "https://git.shadowfacts.net/shadowfacts/grass.git", branch = "custom-global-variables" }
html5ever = "0.27.0"
log = "0.4.22"
markup5ever_rcdom = "0.3.0"

View File

@ -1,5 +1,35 @@
.foo {
.bar {
color: red;
}
@font-face {
font-family: "Equity A";
font-style: normal;
font-weight: normal;
font-stretch: normal;
font-display: auto;
src: url("data:font/woff2;base64," + $equity-a-regular) format("woff2");
}
@font-face {
font-family: "Equity A";
font-style: italic;
font-weight: normal;
font-stretch: normal;
font-display: auto;
src: url("data:font/woff2;base64," + $equity-a-italic) format("woff2");
}
@font-face {
font-family: "Equity A";
font-style: normal;
font-weight: bold;
font-stretch: normal;
font-display: auto;
src: url("data:font/woff2;base64," + $equity-a-bold) format("woff2");
}
@font-face {
font-family: "Equity A";
font-style: italic;
font-weight: bold;
font-stretch: normal;
font-display: auto;
src: url("data:font/woff2;base64," + $equity-a-bold-italic) format("woff2");
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,12 @@
use std::{cell::RefCell, collections::HashSet, io::Write, path::PathBuf, rc::Rc};
use std::{
cell::RefCell,
collections::{HashMap, HashSet},
io::Write,
path::PathBuf,
rc::Rc,
};
use base64::{Engine, prelude::BASE64_STANDARD};
use compute_graph::{
InvalidationSignal,
builder::GraphBuilder,
@ -7,6 +14,7 @@ use compute_graph::{
synchronicity::Asynchronous,
};
use grass::{Fs, Options, OutputStyle};
use grass_compiler::sass_value::{QuoteKind, Value};
use log::error;
use super::{
@ -18,21 +26,55 @@ pub fn make_graph(
builder: &mut GraphBuilder<(), Asynchronous>,
watcher: Rc<RefCell<FileWatcher>>,
) -> Input<()> {
let mut watcher_ = watcher.borrow_mut();
let mut fonts = HashMap::<&'static str, Input<String>>::new();
let filenames: &[&str] = &[
"equity-a-regular",
"equity-a-bold",
"equity-a-italic",
"equity-a-bold-italic",
];
for name in filenames {
fonts.insert(name, read_font(name, builder, &mut *watcher_));
}
drop(watcher_);
let invalidate_css_box = Rc::new(RefCell::new(None));
let (css, invalidate_css) = builder.add_invalidatable_rule(CompileScss {
watcher,
watched: HashSet::new(),
invalidate: Rc::clone(&invalidate_css_box),
fonts,
});
invalidate_css_box.replace(Some(invalidate_css));
css
}
#[derive(InputVisitable)]
fn read_font(
name: &'static str,
builder: &mut GraphBuilder<(), Asynchronous>,
watcher: &mut FileWatcher,
) -> Input<String> {
let mut path = content_path("fonts");
path.push(name);
path.set_extension("woff2");
let (font, invalidate) = builder.add_invalidatable_rule(ReadFont(path.clone()));
watcher.watch(path, move || invalidate.invalidate());
font
}
struct CompileScss {
watcher: Rc<RefCell<FileWatcher>>,
watched: HashSet<PathBuf>,
invalidate: Rc<RefCell<Option<InvalidationSignal>>>,
fonts: HashMap<&'static str, Input<String>>,
}
impl InputVisitable for CompileScss {
fn visit_inputs(&self, visitor: &mut impl compute_graph::rule::InputVisitor) {
for input in self.fonts.values() {
visitor.visit(input);
}
}
}
impl Rule for CompileScss {
type Output = ();
@ -44,8 +86,14 @@ impl Rule for CompileScss {
} else {
OutputStyle::Compressed
};
let options = Options::default().fs(&fs).style(style);
let mut options = Options::default().fs(&fs).style(style);
for (name, input) in self.fonts.iter() {
let value = Value::String(input.value().to_owned(), QuoteKind::None);
options = options.add_custom_var(*name, value);
}
let result = grass::from_path(content_path("css/main.scss"), &options);
let mut watcher = self.watcher.borrow_mut();
for file in read_files.take() {
if !self.watched.contains(&file) {
@ -54,6 +102,7 @@ impl Rule for CompileScss {
watcher.watch(file, move || signal.invalidate());
}
}
match result {
Ok(s) => {
output_writer("css/main.css")
@ -88,3 +137,18 @@ impl<'a> Fs for TrackingFs<'a> {
std::fs::canonicalize(path)
}
}
#[derive(InputVisitable)]
struct ReadFont(PathBuf);
impl Rule for ReadFont {
type Output = String;
fn evaluate(&mut self) -> Self::Output {
match std::fs::read(&self.0) {
Ok(data) => BASE64_STANDARD.encode(data),
Err(e) => {
error!("Error reading font {:?}: {:?}", &self.0, e);
String::new()
}
}
}
}