Skip to content

Commit 1d64a15

Browse files
committed
Add option for unused symbols and refactor css modules
1 parent c20db54 commit 1d64a15

File tree

15 files changed

+337
-168
lines changed

15 files changed

+337
-168
lines changed

node/index.d.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,38 @@ export interface TransformResult {
5555

5656
export type CSSModuleExports = {
5757
/** Maps exported (i.e. original) names to local names. */
58-
[name: string]: CSSModuleExport[]
58+
[name: string]: CSSModuleExport
5959
};
6060

61-
export type CSSModuleExport = LocalCSSModuleExport | DependencyCSSModuleExport;
61+
export interface CSSModuleExport {
62+
/** The local (compiled) name for this export. */
63+
name: string,
64+
/** Whether the export is referenced in this file. */
65+
isReferenced: boolean,
66+
/** Other names that are composed by this export. */
67+
composes: CSSModuleReference[]
68+
}
69+
70+
export type CSSModuleReference = LocalCSSModuleReference | GlobalCSSModuleReference | DependencyCSSModuleReference;
6271

63-
export interface LocalCSSModuleExport {
72+
export interface LocalCSSModuleReference {
6473
type: 'local',
65-
/** The local (compiled) name for this export. */
66-
value: string
74+
/** The local (compiled) name for the reference. */
75+
name: string,
76+
}
77+
78+
export interface GlobalCSSModuleReference {
79+
type: 'global',
80+
/** The referenced global name. */
81+
name: string,
6782
}
6883

69-
export interface DependencyCSSModuleExport {
84+
export interface DependencyCSSModuleReference {
7085
type: 'dependency',
71-
value: {
72-
/** The name to reference within the dependency. */
73-
name: string,
74-
/** The dependency specifier for the referenced file. */
75-
specifier: string
76-
}
86+
/** The name to reference within the dependency. */
87+
name: string,
88+
/** The dependency specifier for the referenced file. */
89+
specifier: string
7790
}
7891

7992
export type Dependency = ImportDependency | UrlDependency;

node/src/lib.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
#[global_allocator]
33
static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
44

5+
use std::collections::HashSet;
56
use serde::{Serialize, Deserialize};
6-
use parcel_css::stylesheet::{StyleSheet, StyleAttribute, ParserOptions, PrinterOptions, PseudoClasses};
7+
use parcel_css::stylesheet::{StyleSheet, StyleAttribute, ParserOptions, PrinterOptions, MinifyOptions, PseudoClasses};
78
use parcel_css::targets::Browsers;
89
use parcel_css::css_modules::CssModuleExports;
910
use parcel_css::dependencies::Dependency;
@@ -115,7 +116,8 @@ struct Config {
115116
pub drafts: Option<Drafts>,
116117
pub css_modules: Option<bool>,
117118
pub analyze_dependencies: Option<bool>,
118-
pub pseudo_classes: Option<OwnedPseudoClasses>
119+
pub pseudo_classes: Option<OwnedPseudoClasses>,
120+
pub unused_symbols: Option<HashSet<String>>
119121
}
120122

121123
#[derive(Debug, Deserialize)]
@@ -154,7 +156,10 @@ fn compile<'i>(code: &'i str, config: &Config) -> Result<TransformResult, Compil
154156
},
155157
css_modules: config.css_modules.unwrap_or(false)
156158
})?;
157-
stylesheet.minify(config.targets); // TODO: should this be conditional?
159+
stylesheet.minify(MinifyOptions {
160+
targets: config.targets,
161+
unused_symbols: config.unused_symbols.clone().unwrap_or_default()
162+
});
158163
let res = stylesheet.to_css(PrinterOptions {
159164
minify: config.minify.unwrap_or(false),
160165
source_map: config.source_map.unwrap_or(false),
@@ -209,7 +214,10 @@ struct AttrResult {
209214

210215
fn compile_attr<'i>(code: &'i str, config: &AttrConfig) -> Result<AttrResult, CompileError<'i>> {
211216
let mut attr = StyleAttribute::parse(&code)?;
212-
attr.minify(config.targets); // TODO: should this be conditional?
217+
attr.minify(MinifyOptions {
218+
targets: config.targets,
219+
..MinifyOptions::default()
220+
});
213221
let res = attr.to_css(PrinterOptions {
214222
minify: config.minify.unwrap_or(false),
215223
source_map: false,

src/css_modules.rs

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,30 @@ use crate::selector::Selectors;
99
use serde::Serialize;
1010
use crate::error::PrinterError;
1111

12-
#[derive(PartialEq, Eq, Hash, Debug, Clone, Serialize)]
13-
#[serde(tag = "type", content = "value", rename_all = "lowercase")]
14-
pub enum CssModuleExport {
15-
Local(String),
12+
#[derive(PartialEq, Debug, Clone, Serialize)]
13+
#[serde(tag = "type", rename_all = "lowercase")]
14+
pub enum CssModuleReference {
15+
Local {
16+
name: String,
17+
},
18+
Global {
19+
name: String
20+
},
1621
Dependency {
1722
name: String,
1823
specifier: String
1924
}
2025
}
2126

22-
pub type CssModuleExports = HashMap<String, Vec<CssModuleExport>>;
27+
#[derive(PartialEq, Debug, Clone, Serialize)]
28+
#[serde(rename_all = "camelCase")]
29+
pub struct CssModuleExport {
30+
pub name: String,
31+
pub composes: Vec<CssModuleReference>,
32+
pub is_referenced: bool
33+
}
34+
35+
pub type CssModuleExports = HashMap<String, CssModuleExport>;
2336

2437
lazy_static! {
2538
static ref ENCODER: Encoding = {
@@ -35,50 +48,49 @@ pub(crate) struct CssModule<'a> {
3548
}
3649

3750
impl<'a> CssModule<'a> {
38-
pub fn add_export(&mut self, name: String, export: CssModuleExport) {
39-
match self.exports.entry(name) {
51+
pub fn add_local(&mut self, exported: &str, local: &str) {
52+
let hash = &self.hash;
53+
self.exports.entry(exported.into())
54+
.or_insert_with(|| CssModuleExport {
55+
name: format!("{}_{}", local, hash),
56+
composes: vec![],
57+
is_referenced: false
58+
});
59+
}
60+
61+
pub fn reference(&mut self, name: &str) {
62+
match self.exports.entry(name.into()) {
4063
std::collections::hash_map::Entry::Occupied(mut entry) => {
41-
if !entry.get().contains(&export) {
42-
entry.get_mut().push(export);
43-
}
64+
entry.get_mut().is_referenced = true;
4465
}
4566
std::collections::hash_map::Entry::Vacant(entry) => {
46-
let mut items = Vec::new();
47-
if !items.contains(&export) {
48-
items.push(export);
49-
}
50-
entry.insert(items);
67+
entry.insert(CssModuleExport {
68+
name: format!("{}_{}", name, self.hash),
69+
composes: vec![],
70+
is_referenced: true
71+
});
5172
}
5273
}
5374
}
5475

55-
pub fn add_local(&mut self, exported: &str, local: &str) {
56-
let local = CssModuleExport::Local(format!("{}_{}", local, self.hash));
57-
self.add_export(exported.into(), local);
58-
}
59-
60-
pub fn add_global(&mut self, exported: &str, global: &str) {
61-
self.add_export(exported.into(), CssModuleExport::Local(global.into()))
62-
}
63-
64-
pub fn add_dependency(&mut self, exported: &str, name: &str, specifier: &str) {
65-
let dependency = CssModuleExport::Dependency {
66-
name: name.into(),
67-
specifier: specifier.into()
68-
};
69-
self.add_export(exported.into(), dependency)
70-
}
71-
7276
pub fn handle_composes(&mut self, selectors: &SelectorList<Selectors>, composes: &Composes) -> Result<(), PrinterError> {
7377
for sel in &selectors.0 {
7478
if sel.len() == 1 {
7579
match sel.iter_raw_match_order().next().unwrap() {
7680
parcel_selectors::parser::Component::Class(ref id) => {
7781
for name in &composes.names {
78-
match &composes.from {
79-
None => self.add_local(&id.0, &name.0),
80-
Some(ComposesFrom::Global) => self.add_global(&id.0, &name.0),
81-
Some(ComposesFrom::File(file)) => self.add_dependency(&id.0, &name.0, &file)
82+
let reference = match &composes.from {
83+
None => CssModuleReference::Local { name: format!("{}_{}", name.0, self.hash) },
84+
Some(ComposesFrom::Global) => CssModuleReference::Global { name: name.0.clone() },
85+
Some(ComposesFrom::File(file)) => CssModuleReference::Dependency {
86+
name: name.0.clone(),
87+
specifier: file.clone()
88+
}
89+
};
90+
91+
let export = self.exports.get_mut(&id.0).unwrap();
92+
if !export.composes.contains(&reference) {
93+
export.composes.push(reference);
8294
}
8395
}
8496
continue;

0 commit comments

Comments
 (0)