Skip to content

Commit

Permalink
Add font weight, style to css and js properties
Browse files Browse the repository at this point in the history
  • Loading branch information
wbinnssmith committed Dec 8, 2022
1 parent cd4a9f2 commit 6cd213a
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 35 deletions.
130 changes: 99 additions & 31 deletions crates/next-core/src/next_font_google/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
use indexmap::IndexMap;
use indoc::formatdoc;
use once_cell::sync::Lazy;
use turbo_tasks::primitives::{OptionStringVc, StringVc};
use turbo_tasks::primitives::{OptionStringVc, OptionU16Vc, StringVc};
use turbo_tasks_fetch::fetch;
use turbo_tasks_fs::{FileContent, FileSystemPathVc};
use turbopack_core::{
Expand All @@ -12,16 +12,17 @@ use turbopack_core::{
ImportMappingReplacementVc, ImportMappingVc,
},
parse::{Request, RequestVc},
pattern::QueryMapVc,
ResolveResult,
},
virtual_asset::VirtualAssetVc,
};

use self::options::FontWeights;
use crate::{
embed_js::attached_next_js_package_path,
next_font_google::{
options::FontDataEntry,
request::NextFontRequest,
util::{get_font_axes, get_stylesheet_url},
},
};
Expand Down Expand Up @@ -62,12 +63,14 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
let Request::Module {
module: _,
path: _,
query,
query: query_vc
} = request else {
return Ok(ImportMapResult::NoEntry.into());
};

let query = &*query.await?;
let query = &*query_vc.await?;
let options = font_options_from_query_map(*query_vc);
let properties = get_font_css_properties(options).await?;
let js_asset = VirtualAssetVc::new(
attached_next_js_package_path(self.project_path)
.join("internal/font/google/inter.js"),
Expand All @@ -76,11 +79,27 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
r#"
import cssModule from "@vercel/turbopack-next/internal/font/google/cssmodule.module.css?{}";
export default {{
className: cssModule.className
className: cssModule.className,
style: {{
fontFamily: "{}",
{}{}
}}
}};
"#,
// Pass along whichever options we received to the css handler
qstring::QString::new(query.as_ref().unwrap().iter().collect())
qstring::QString::new(query.as_ref().unwrap().iter().collect()),
properties.font_family.await?,
properties
.weight
.await?
.map(|w| format!("fontWeight: {},\n", w))
.unwrap_or_else(|| "".to_owned()),
properties
.style
.await?
.as_ref()
.map(|s| format!("fontStyle: \"{}\",\n", s))
.unwrap_or_else(|| "".to_owned()),
)
.into(),
)
Expand Down Expand Up @@ -122,23 +141,8 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
return Ok(ImportMapResult::NoEntry.into());
};

let query_map = &*query.await?;
// These are invariants from the next/font swc transform. Regular errors instead
// of Issues should be okay.
let query_map = query_map
.as_ref()
.context("@next/font/google queries must exist")?;

if query_map.len() != 1 {
bail!("@next/font/google queries must only have one entry");
}

let Some((json, _)) = query_map.iter().next() else {
bail!("Expected one entry");
};

let request: StringVc = StringVc::cell(json.to_owned());
let stylesheet_url = get_stylesheet_url_from_request(request);
let options = font_options_from_query_map(*query);
let stylesheet_url = get_stylesheet_url_from_options(options);

// TODO(WEB-274): Handle this failing (e.g. connection issues). This should be
// an Issue.
Expand All @@ -158,7 +162,7 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
}

let stylesheet = &*stylesheet_res.body.to_string().await?;
let options = options_from_request(request).await?;
let properties = get_font_css_properties(options).await?;

let css_asset = VirtualAssetVc::new(
attached_next_js_package_path(self.project_path)
Expand All @@ -169,11 +173,23 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
{}
.className {{
font-family: "{}";
font-family: {};
{}{}
}}
"#,
stylesheet,
options.font_family
properties.font_family.await?,
properties
.weight
.await?
.map(|w| format!("font-weight: {};\n", w))
.unwrap_or_else(|| "".to_owned()),
properties
.style
.await?
.as_ref()
.map(|s| format!("font-style: {};\n", s))
.unwrap_or_else(|| "".to_owned()),
)
.into(),
)
Expand All @@ -185,8 +201,8 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
}

#[turbo_tasks::function]
async fn get_stylesheet_url_from_request(request_json: StringVc) -> Result<StringVc> {
let options = options_from_request(request_json).await?;
async fn get_stylesheet_url_from_options(options: NextFontGoogleOptionsVc) -> Result<StringVc> {
let options = options.await?;

Ok(StringVc::cell(get_stylesheet_url(
GOOGLE_FONTS_STYLESHEET_URL,
Expand All @@ -205,9 +221,61 @@ async fn get_stylesheet_url_from_request(request_json: StringVc) -> Result<Strin
#[turbo_tasks::value(transparent)]
struct NextFontGoogleOptions(self::options::NextFontGoogleOptions);

#[turbo_tasks::value(transparent)]
struct FontCssProperties {
font_family: StringVc,
weight: OptionU16Vc,
style: OptionStringVc,
}

#[turbo_tasks::function]
async fn options_from_request(request: StringVc) -> Result<NextFontGoogleOptionsVc> {
let request: NextFontRequest = serde_json::from_str(&request.await?)?;
async fn get_font_css_properties(options: NextFontGoogleOptionsVc) -> Result<FontCssPropertiesVc> {
let options = &*options.await?;

let font_family = format!(
"'{}'{}",
options.font_family,
options
.fallback
.as_ref()
.map(|fallback| {
", ".to_owned()
+ &fallback
.iter()
.map(|f| format!("'{}'", f))
.collect::<Vec<String>>()
.join(", ")
})
.unwrap_or_else(|| "".to_owned())
);

Ok(FontCssPropertiesVc::cell(FontCssProperties {
font_family: StringVc::cell(font_family),
weight: OptionU16Vc::cell(match &options.weights {
FontWeights::Variable => None,
FontWeights::Fixed(weights) => weights.first().cloned(),
}),
style: OptionStringVc::cell(options.styles.first().cloned()),
}))
}

#[turbo_tasks::function]
async fn font_options_from_query_map(query: QueryMapVc) -> Result<NextFontGoogleOptionsVc> {
let query_map = &*query.await?;
// These are invariants from the next/font swc transform. Regular errors instead
// of Issues should be okay.
let query_map = query_map
.as_ref()
.context("@next/font/google queries must exist")?;

if query_map.len() != 1 {
bail!("@next/font/google queries must only have one entry");
}

let Some((json, _)) = query_map.iter().next() else {
bail!("Expected one entry");
};

self::options::options_from_request(&request, &FONT_DATA).map(NextFontGoogleOptionsVc::cell)
self::options::options_from_request(&serde_json::from_str(json)?, &FONT_DATA)
.map(NextFontGoogleOptionsVc::cell)
}
11 changes: 8 additions & 3 deletions crates/next-core/src/next_font_google/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub struct NextFontGoogleOptions {
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)]
pub enum FontWeights {
Variable,
Fixed(IndexSet<String>),
Fixed(IndexSet<u16>),
}

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -64,7 +64,7 @@ pub fn options_from_request(
let font_family = request.import.replace('_', " ");
let font_data = data.get(&font_family).context("Unknown font")?;

let requested_weights = argument
let requested_weights: IndexSet<String> = argument
.and_then(|argument| {
argument.weight.as_ref().map(|w| match w {
OneOrManyStrings::One(one) => indexset! {one.to_owned()},
Expand Down Expand Up @@ -114,7 +114,12 @@ pub fn options_from_request(
}
}

FontWeights::Fixed(requested_weights)
let mut weights = indexset! {};
for weight in requested_weights {
weights.insert(weight.parse()?);
}

FontWeights::Fixed(weights)
};

if styles.is_empty() {
Expand Down
3 changes: 2 additions & 1 deletion crates/next-core/src/next_font_google/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ pub(crate) fn get_font_axes(
variable_axes: Some(variable_axes),
})
}

FontWeights::Fixed(weights) => Ok(FontAxes {
wght: weights.clone(),
wght: IndexSet::from_iter(weights.iter().map(|w| w.to_string())),
ital,
variable_axes: None,
}),
Expand Down
3 changes: 3 additions & 0 deletions crates/turbo-tasks/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ impl StringVc {
}
}

#[turbo_tasks::value(transparent)]
pub struct OptionU16(Option<u16>);

#[turbo_tasks::value(transparent)]
pub struct U64(u64);

Expand Down

0 comments on commit 6cd213a

Please sign in to comment.