Skip to content

Commit 62bf352

Browse files
committed
Implement unicode-range syntax
Closes parcel-bundler#86
1 parent 048c3fe commit 62bf352

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5731,6 +5731,20 @@ mod tests {
57315731
minify_test("@font-face {font-weight: 400 400}", "@font-face{font-weight:400}");
57325732
minify_test("@font-face {font-stretch: 50% 200%}", "@font-face{font-stretch:50% 200%}");
57335733
minify_test("@font-face {font-stretch: 50% 50%}", "@font-face{font-stretch:50%}");
5734+
minify_test("@font-face {unicode-range: U+26;}", "@font-face{unicode-range:U+26}");
5735+
minify_test("@font-face {unicode-range: u+26;}", "@font-face{unicode-range:U+26}");
5736+
minify_test("@font-face {unicode-range: U+0-7F;}", "@font-face{unicode-range:U+0-7F}");
5737+
minify_test("@font-face {unicode-range: U+0025-00FF;}", "@font-face{unicode-range:U+25-FF}");
5738+
minify_test("@font-face {unicode-range: U+4??;}", "@font-face{unicode-range:U+4??}");
5739+
minify_test("@font-face {unicode-range: U+400-4FF;}", "@font-face{unicode-range:U+4??}");
5740+
minify_test("@font-face {unicode-range: U+0025-00FF, U+4??;}", "@font-face{unicode-range:U+25-FF,U+4??}");
5741+
minify_test("@font-face {unicode-range: U+A5, U+4E00-9FFF, U+30??, U+FF00-FF9F;}", "@font-face{unicode-range:U+A5,U+4E00-9FFF,U+30??,U+FF00-FF9F}");
5742+
minify_test("@font-face {unicode-range: U+????;}", "@font-face{unicode-range:U+????}");
5743+
minify_test("@font-face {unicode-range: U+0000-FFFF;}", "@font-face{unicode-range:U+????}");
5744+
minify_test("@font-face {unicode-range: U+10????;}", "@font-face{unicode-range:U+10????}");
5745+
minify_test("@font-face {unicode-range: U+100000-10FFFF;}", "@font-face{unicode-range:U+10????}");
5746+
minify_test("@font-face {unicode-range: U+1e1e?;}", "@font-face{unicode-range:U+1E1E?}");
5747+
minify_test("@font-face {unicode-range: u+????, U+1????, U+10????;}", "@font-face{unicode-range:U+????,U+1????,U+10????}");
57345748
}
57355749

57365750
#[test]

src/rules/font_face.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::properties::custom::CustomProperty;
99
use crate::macros::enum_property;
1010
use crate::values::{url::Url};
1111
use crate::error::{ParserError, PrinterError};
12+
use std::fmt::Write;
1213

1314
#[derive(Debug, PartialEq, Clone)]
1415
pub struct FontFaceRule<'i> {
@@ -23,6 +24,7 @@ pub enum FontFaceProperty<'i> {
2324
FontStyle(FontStyle),
2425
FontWeight(Size2D<FontWeight>),
2526
FontStretch(Size2D<FontStretch>),
27+
UnicodeRange(Vec<UnicodeRange>),
2628
Custom(CustomProperty<'i>)
2729
}
2830

@@ -254,6 +256,60 @@ impl ToCss for FontTechnology {
254256
}
255257
}
256258

259+
impl<'i> Parse<'i> for UnicodeRange {
260+
fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
261+
let range = UnicodeRange::parse(input)?;
262+
Ok(range)
263+
}
264+
}
265+
266+
impl ToCss for UnicodeRange {
267+
fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> where W: std::fmt::Write {
268+
// Attempt to optimize the range to use question mark syntax.
269+
if self.start != self.end {
270+
// Find the first hex digit that differs between the start and end values.
271+
let mut shift = 24;
272+
let mut mask = 0xf << shift;
273+
while shift > 0 {
274+
let c1 = self.start & mask;
275+
let c2 = self.end & mask;
276+
if c1 != c2 {
277+
break
278+
}
279+
280+
mask = mask >> 4;
281+
shift -= 4;
282+
}
283+
284+
// Get the remainder of the value. This must be 0x0 to 0xf for the rest
285+
// of the value to use the question mark syntax.
286+
let remainder_mask = (0xf << shift) - 1 | (1 << shift);
287+
let start_remainder = self.start & remainder_mask;
288+
let end_remainder = self.end & remainder_mask;
289+
290+
if start_remainder == 0 && end_remainder == remainder_mask {
291+
shift += 4;
292+
let start = (self.start & !remainder_mask) >> shift;
293+
if start != 0 {
294+
write!(dest, "U+{:X}", start)?;
295+
} else {
296+
dest.write_str("U+")?;
297+
}
298+
299+
while shift > 0 {
300+
dest.write_char('?')?;
301+
shift -= 4;
302+
}
303+
304+
return Ok(())
305+
}
306+
}
307+
308+
cssparser::ToCss::to_css(self, dest)?;
309+
Ok(())
310+
}
311+
}
312+
257313
pub(crate) struct FontFaceDeclarationParser;
258314

259315
/// Parse a declaration within {} block: `color: blue`
@@ -285,6 +341,7 @@ impl<'i> cssparser::DeclarationParser<'i> for FontFaceDeclarationParser {
285341
"font-weight" => property!(FontWeight, Size2D<FontWeight>),
286342
"font-style" => property!(FontStyle, FontStyle),
287343
"font-stretch" => property!(FontStretch, Size2D<FontStretch>),
344+
"unicode-range" => property!(UnicodeRange, Vec<UnicodeRange>),
288345
_ => {}
289346
}
290347

@@ -350,6 +407,7 @@ impl<'i> ToCss for FontFaceProperty<'i> {
350407
FontStyle(value) => property!("font-style", value),
351408
FontWeight(value) => property!("font-weight", value),
352409
FontStretch(value) => property!("font-stretch", value),
410+
UnicodeRange(value) => property!("unicode-range", value),
353411
Custom(custom) => {
354412
dest.write_str(custom.name.as_ref())?;
355413
dest.delim(':', false)?;

0 commit comments

Comments
 (0)