forked from parcel-bundler/lightningcss
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtargets.rs
More file actions
129 lines (116 loc) · 4.45 KB
/
targets.rs
File metadata and controls
129 lines (116 loc) · 4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Browser target options.
// This file is autogenerated by build-prefixes.js. DO NOT EDIT!
use serde::{Deserialize, Serialize};
/// Browser versions to compile CSS for.
///
/// Versions are represented as a single 24-bit integer, with one byte
/// per `major.minor.patch` component.
///
/// # Example
///
/// This example represents a target of Safari 13.2.0.
///
/// ```
/// use lightningcss::targets::Browsers;
///
/// let targets = Browsers {
/// safari: Some((13 << 16) | (2 << 8)),
/// ..Browsers::default()
/// };
/// ```
#[derive(Serialize, Debug, Deserialize, Clone, Copy, Default)]
#[allow(missing_docs)]
pub struct Browsers {
pub android: Option<u32>,
pub chrome: Option<u32>,
pub edge: Option<u32>,
pub firefox: Option<u32>,
pub ie: Option<u32>,
pub ios_saf: Option<u32>,
pub opera: Option<u32>,
pub safari: Option<u32>,
pub samsung: Option<u32>,
}
#[cfg(feature = "browserslist")]
impl Browsers {
/// Parses a list of browserslist queries into Lightning CSS targets.
pub fn from_browserslist<S: AsRef<str>, I: IntoIterator<Item = S>>(
query: I,
) -> Result<Option<Browsers>, browserslist::Error> {
use browserslist::{resolve, Opts};
Self::from_distribs(resolve(query, &Opts::new())?)
}
/// Finds browserslist configuration, selects queries by environment and loads the resulting queries into LightningCSS targets.
///
/// Configuration resolution is modeled after the original `browserslist` nodeJS package.
/// The configuration is resolved in the following order:
///
/// - If a `BROWSERSLIST` environment variable is present, then load targets from its value. This is analog to the `--targets` CLI option.
/// Example: `BROWSERSLIST="firefox ESR" lightningcss [OPTIONS] <INPUT_FILE>`
/// - If a `BROWSERSLIST_CONFIG` environment variable is present, then resolve the file at the provided path.
/// Then parse and use targets from `package.json` or any browserslist configuration file pointed to by the environment variable.
/// Example: `BROWSERSLIST_CONFIG="../config/browserslist" lightningcss [OPTIONS] <INPUT_FILE>`
/// - If none of the above apply, then find, parse and use targets from the first `browserslist`, `.browserslistrc`
/// or `package.json` configuration file in any parent directory.
///
/// When using parsed configuration from `browserslist`, `.browserslistrc` or `package.json` configuration files,
/// the environment determined by:
///
/// - the `BROWSERSLIST_ENV` environment variable if present,
/// - otherwise the `NODE_ENV` environment varialbe if present,
/// - otherwise `production` is used.
///
/// If no targets are found for the resulting environment, then the `defaults` configuration section is used.
pub fn load_browserslist() -> Result<Option<Browsers>, browserslist::Error> {
use browserslist::{execute, Opts};
Self::from_distribs(execute(&Opts::new())?)
}
fn from_distribs(distribs: Vec<browserslist::Distrib>) -> Result<Option<Browsers>, browserslist::Error> {
let mut browsers = Browsers::default();
let mut has_any = false;
for distrib in distribs {
macro_rules! browser {
($browser: ident) => {{
if let Some(v) = parse_version(distrib.version()) {
if browsers.$browser.is_none() || v < browsers.$browser.unwrap() {
browsers.$browser = Some(v);
has_any = true;
}
}
}};
}
match distrib.name() {
"android" => browser!(android),
"chrome" | "and_chr" => browser!(chrome),
"edge" => browser!(edge),
"firefox" | "and_ff" => browser!(firefox),
"ie" => browser!(ie),
"ios_saf" => browser!(ios_saf),
"opera" | "op_mob" => browser!(opera),
"safari" => browser!(safari),
"samsung" => browser!(samsung),
_ => {}
}
}
if !has_any {
return Ok(None);
}
Ok(Some(browsers))
}
}
#[cfg(feature = "browserslist")]
fn parse_version(version: &str) -> Option<u32> {
let version = version.split('-').next();
if version.is_none() {
return None;
}
let mut version = version.unwrap().split('.');
let major = version.next().and_then(|v| v.parse::<u32>().ok());
if let Some(major) = major {
let minor = version.next().and_then(|v| v.parse::<u32>().ok()).unwrap_or(0);
let patch = version.next().and_then(|v| v.parse::<u32>().ok()).unwrap_or(0);
let v: u32 = (major & 0xff) << 16 | (minor & 0xff) << 8 | (patch & 0xff);
return Some(v);
}
None
}