parcel_css/
targets.rs

1//! Browser target options.
2// This file is autogenerated by build-prefixes.js. DO NOT EDIT!
3
4use serde::{Deserialize, Serialize};
5
6/// Browser versions to compile CSS for.
7///
8/// Versions are represented as a single 24-bit integer, with one byte
9/// per `major.minor.patch` component.
10///
11/// # Example
12///
13/// This example represents a target of Safari 13.2.0.
14///
15/// ```
16/// use parcel_css::targets::Browsers;
17///
18/// let targets = Browsers {
19///   safari: Some((13 << 16) | (2 << 8)),
20///   ..Browsers::default()
21/// };
22/// ```
23#[derive(Serialize, Debug, Deserialize, Clone, Copy, Default)]
24#[allow(missing_docs)]
25pub struct Browsers {
26  pub android: Option<u32>,
27  pub chrome: Option<u32>,
28  pub edge: Option<u32>,
29  pub firefox: Option<u32>,
30  pub ie: Option<u32>,
31  pub ios_saf: Option<u32>,
32  pub opera: Option<u32>,
33  pub safari: Option<u32>,
34  pub samsung: Option<u32>,
35}
36
37#[cfg(feature = "browserslist")]
38impl Browsers {
39  /// Parses a list of browserslist queries into Parcel CSS targets.
40  pub fn from_browserslist<S: AsRef<str>, I: IntoIterator<Item = S>>(
41    query: I,
42  ) -> Result<Option<Browsers>, browserslist::Error> {
43    use browserslist::{resolve, Opts};
44
45    let res = resolve(query, &Opts::new())?;
46
47    let mut browsers = Browsers::default();
48    let mut has_any = false;
49    for distrib in res {
50      macro_rules! browser {
51        ($browser: ident) => {{
52          if let Some(v) = parse_version(distrib.version()) {
53            if browsers.$browser.is_none() || v < browsers.$browser.unwrap() {
54              browsers.$browser = Some(v);
55              has_any = true;
56            }
57          }
58        }};
59      }
60
61      match distrib.name() {
62        "android" => browser!(android),
63        "chrome" | "and_chr" => browser!(chrome),
64        "edge" => browser!(edge),
65        "firefox" | "and_ff" => browser!(firefox),
66        "ie" => browser!(ie),
67        "ios_saf" => browser!(ios_saf),
68        "opera" | "op_mob" => browser!(opera),
69        "safari" => browser!(safari),
70        "samsung" => browser!(samsung),
71        _ => {}
72      }
73    }
74
75    if !has_any {
76      return Ok(None);
77    }
78
79    Ok(Some(browsers))
80  }
81}
82
83#[cfg(feature = "browserslist")]
84fn parse_version(version: &str) -> Option<u32> {
85  let version = version.split('-').next();
86  if version.is_none() {
87    return None;
88  }
89
90  let mut version = version.unwrap().split('.');
91  let major = version.next().and_then(|v| v.parse::<u32>().ok());
92  if let Some(major) = major {
93    let minor = version.next().and_then(|v| v.parse::<u32>().ok()).unwrap_or(0);
94    let patch = version.next().and_then(|v| v.parse::<u32>().ok()).unwrap_or(0);
95    let v: u32 = (major & 0xff) << 16 | (minor & 0xff) << 8 | (patch & 0xff);
96    return Some(v);
97  }
98
99  None
100}