Skip to content

Commit b4d3733

Browse files
authored
Add support for system-ui fallbacks (parcel-bundler#182)
1 parent 87eeca7 commit b4d3733

File tree

5 files changed

+132
-4
lines changed

5 files changed

+132
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ A CSS parser, transformer, and minifier written in Rust.
4545
- Two-value `overflow` shorthand
4646
- Media query range syntax (e.g. `@media (width <= 100px)` or `@media (100px < width < 500px)`)
4747
- Multi-value `display` property (e.g. `inline flex`)
48+
- `system-ui` font family fallbacks
4849
- **CSS modules**`@parcel/css` supports compiling a subset of [CSS modules](https://github.com/css-modules/css-modules) features.
4950
- Locally scoped class and id selectors
5051
- Locally scoped custom identifiers, e.g. `@keyframes` names, grid lines/areas, `@counter-style` names, etc.

scripts/build-prefixes.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ let cssFeatures = [
168168
'css-rrggbbaa',
169169
'css-nesting',
170170
'css-not-sel-list',
171-
'css-has'
171+
'css-has',
172+
'font-family-system-ui'
172173
];
173174

174175
let compat = new Map();
@@ -315,11 +316,12 @@ use serde::{Deserialize, Serialize};
315316
/// use parcel_css::targets::Browsers;
316317
///
317318
/// let targets = Browsers {
318-
/// safari: (13 << 16) | (2 << 8),
319+
/// safari: Some((13 << 16) | (2 << 8)),
319320
/// ..Browsers::default()
320321
/// };
321322
/// \`\`\`
322323
#[derive(Serialize, Debug, Deserialize, Clone, Copy, Default)]
324+
#[allow(missing_docs)]
323325
pub struct Browsers {
324326
pub ${allBrowsers.join(': Option<u32>,\n pub ')}: Option<u32>
325327
}

src/compat.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub enum Feature {
3636
CustomMediaQueries,
3737
Dialog,
3838
DoublePositionGradients,
39+
FontFamilySystemUi,
3940
FormValidation,
4041
Fullscreen,
4142
LabColors,
@@ -1272,6 +1273,51 @@ impl Feature {
12721273
return false;
12731274
}
12741275
}
1276+
Feature::FontFamilySystemUi => {
1277+
if let Some(version) = browsers.edge {
1278+
if version < 5177344 {
1279+
return false;
1280+
}
1281+
}
1282+
if let Some(version) = browsers.firefox {
1283+
if version < 6029312 {
1284+
return false;
1285+
}
1286+
}
1287+
if let Some(version) = browsers.chrome {
1288+
if version < 3670016 {
1289+
return false;
1290+
}
1291+
}
1292+
if let Some(version) = browsers.safari {
1293+
if version < 720896 {
1294+
return false;
1295+
}
1296+
}
1297+
if let Some(version) = browsers.opera {
1298+
if version < 2818048 {
1299+
return false;
1300+
}
1301+
}
1302+
if let Some(version) = browsers.ios_saf {
1303+
if version < 720896 {
1304+
return false;
1305+
}
1306+
}
1307+
if let Some(version) = browsers.android {
1308+
if version < 6553600 {
1309+
return false;
1310+
}
1311+
}
1312+
if let Some(version) = browsers.samsung {
1313+
if version < 393728 {
1314+
return false;
1315+
}
1316+
}
1317+
if browsers.ie.is_some() {
1318+
return false;
1319+
}
1320+
}
12751321
Feature::DoublePositionGradients => {
12761322
if let Some(version) = browsers.chrome {
12771323
if version < 4653056 {

src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4688,6 +4688,42 @@ mod tests {
46884688
"@font-face { font-family: 'revert-layer'; }",
46894689
"@font-face{font-family:\"revert-layer\"}",
46904690
);
4691+
4692+
prefix_test(
4693+
r#"
4694+
.foo {
4695+
font-family: Helvetica, system-ui, sans-serif;
4696+
}
4697+
"#,
4698+
indoc! {r#"
4699+
.foo {
4700+
font-family: Helvetica, system-ui, AppleSystem, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
4701+
}
4702+
"#
4703+
},
4704+
Browsers {
4705+
safari: Some(8 << 16),
4706+
..Browsers::default()
4707+
},
4708+
);
4709+
4710+
prefix_test(
4711+
r#"
4712+
.foo {
4713+
font: 100%/1.5 Helvetica, system-ui, sans-serif;
4714+
}
4715+
"#,
4716+
indoc! {r#"
4717+
.foo {
4718+
font: 100% / 1.5 Helvetica, system-ui, AppleSystem, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
4719+
}
4720+
"#
4721+
},
4722+
Browsers {
4723+
safari: Some(8 << 16),
4724+
..Browsers::default()
4725+
},
4726+
);
46914727
}
46924728

46934729
#[test]

src/properties/font.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! CSS properties related to fonts.
22
33
use super::{Property, PropertyId};
4+
use crate::compat::Feature;
45
use crate::context::PropertyHandlerContext;
56
use crate::declaration::{DeclarationBlock, DeclarationList};
67
use crate::error::{ParserError, PrinterError};
@@ -833,14 +834,17 @@ impl<'i> PropertyHandler<'i> for FontHandler<'i> {
833834
true
834835
}
835836

836-
fn finalize(&mut self, decls: &mut DeclarationList<'i>, _: &mut PropertyHandlerContext<'i, '_>) {
837+
fn finalize(&mut self, decls: &mut DeclarationList<'i>, context: &mut PropertyHandlerContext<'i, '_>) {
837838
if !self.has_any {
838839
return;
839840
}
840841

841842
self.has_any = false;
842843

843-
let family = std::mem::take(&mut self.family);
844+
let family = compatible_font_family(
845+
std::mem::take(&mut self.family),
846+
context.is_supported(Feature::FontFamilySystemUi),
847+
);
844848
let size = std::mem::take(&mut self.size);
845849
let style = std::mem::take(&mut self.style);
846850
let weight = std::mem::take(&mut self.weight);
@@ -908,6 +912,45 @@ impl<'i> PropertyHandler<'i> for FontHandler<'i> {
908912
}
909913
}
910914

915+
const SYSTEM_UI: FontFamily = FontFamily::Generic(GenericFontFamily::SystemUI);
916+
917+
const DEFAULT_SYSTEM_FONTS: &[&str] = &[
918+
// #1: Supported as the -apple-system value (only on Mac)
919+
"AppleSystem",
920+
// #2: Supported as the 'BlinkMacSystemFont' value (only on Mac)
921+
"BlinkMacSystemFont",
922+
"Segoe UI", // Windows >= Vista
923+
"Roboto", // Android >= 4
924+
"Noto Sans", // Plasma >= 5.5
925+
"Ubuntu", // Ubuntu >= 10.10
926+
"Cantarell", // GNOME >= 3
927+
"Helvetica Neue",
928+
];
929+
930+
/// [`system-ui`](https://www.w3.org/TR/css-fonts-4/#system-ui-def) is a special generic font family
931+
/// It is platform dependent but if not supported by the target will simply be ignored
932+
/// This list is an attempt at providing that support
933+
#[inline]
934+
fn compatible_font_family(mut family: Option<Vec<FontFamily>>, is_supported: bool) -> Option<Vec<FontFamily>> {
935+
936+
if is_supported {
937+
return family;
938+
}
939+
940+
if let Some(families) = &mut family {
941+
if let Some(position) = families.iter().position(|v| *v == SYSTEM_UI) {
942+
families.splice(
943+
(position + 1)..(position + 1),
944+
DEFAULT_SYSTEM_FONTS
945+
.iter()
946+
.map(|name| FontFamily::FamilyName(CowArcStr::from(*name))),
947+
);
948+
}
949+
}
950+
951+
return family;
952+
}
953+
911954
#[inline]
912955
fn is_font_property(property_id: &PropertyId) -> bool {
913956
match property_id {

0 commit comments

Comments
 (0)