yak-swc 9.10.2 → 9.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # yak-swc
2
2
 
3
+ ## 9.10.3
4
+
3
5
  ## 9.10.2
4
6
 
5
7
  ## 9.10.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yak-swc",
3
- "version": "9.10.2",
3
+ "version": "9.10.3",
4
4
  "description": "next-yak rust based swc plugin to compile styled components at build time",
5
5
  "keywords": [
6
6
  "css-in-js",
@@ -1223,12 +1223,19 @@ where
1223
1223
  let is_top_level = !self.is_inside_css_expression();
1224
1224
  let current_variable_id = self.get_current_component_id();
1225
1225
  let is_default_exported = self.is_default_exported(&current_variable_id);
1226
+ // Exported through a local export list e.g. `export { Button, Button as Alias }`
1227
+ let local_export_names = self
1228
+ .variables
1229
+ .get_local_export_names(&current_variable_id.id)
1230
+ .to_vec();
1231
+ let is_exported =
1232
+ self.current_exported || is_default_exported || !local_export_names.is_empty();
1226
1233
 
1227
1234
  let mut is_exported_styled = false;
1228
1235
  let mut transform: Box<dyn YakTransform> = match yak_library_function_name.deref() {
1229
1236
  // Styled Components transform works only on top level
1230
1237
  "styled" if is_top_level => {
1231
- is_exported_styled = self.current_exported || is_default_exported;
1238
+ is_exported_styled = is_exported;
1232
1239
  // Track exported styled component names for $RefreshReg$ injection
1233
1240
  if self.react_refresh_reg && is_exported_styled {
1234
1241
  let name = current_variable_id.to_readable_string();
@@ -1240,7 +1247,7 @@ where
1240
1247
  &mut self.naming_convention,
1241
1248
  current_variable_id.clone(),
1242
1249
  self.display_names,
1243
- self.current_exported || is_default_exported,
1250
+ is_exported,
1244
1251
  self.import_mode.transpilation_mode(),
1245
1252
  ))
1246
1253
  }
@@ -1276,7 +1283,7 @@ where
1276
1283
  "css" if is_top_level => Box::new(TransformCssMixin::new(
1277
1284
  &mut self.naming_convention,
1278
1285
  current_variable_id.clone(),
1279
- self.current_exported || is_default_exported,
1286
+ is_exported,
1280
1287
  self.inside_element_with_css_attribute,
1281
1288
  self.import_mode.transpilation_mode(),
1282
1289
  )),
@@ -1358,7 +1365,7 @@ where
1358
1365
  let result_span = transform_result.expression.span();
1359
1366
  // A globalStyle literal that errored produced malformed declarations; keep the
1360
1367
  // bare `globalStyle()` call as the anchor but emit no extracted CSS for it.
1361
- if (!css_code.is_empty() || self.current_exported) && is_top_level && !self.global_style_error {
1368
+ if (!css_code.is_empty() || is_exported) && is_top_level && !self.global_style_error {
1362
1369
  if let Some(comment_prefix) = transform_result.css.comment_prefix {
1363
1370
  // Don't add invalid CSS rules to the list of all CSS rules
1364
1371
  // Mixin code should always be used in other components so that they target the correct element
@@ -1384,6 +1391,24 @@ where
1384
1391
  text: format!("{}\n{}\n", comment_prefix, css_code.trim()).into(),
1385
1392
  },
1386
1393
  );
1394
+ // One more marker for every other name in a local export list
1395
+ // e.g. `export { Button as Alias }` or `export { Button as default }`
1396
+ let local_name = current_variable_id.parts.first();
1397
+ for exported_name in &local_export_names {
1398
+ if Some(exported_name) == local_name {
1399
+ continue;
1400
+ }
1401
+ if let Some(text) = transform.get_export_name_comment(exported_name, css_code.trim()) {
1402
+ self.comments.add_leading(
1403
+ result_span.lo,
1404
+ Comment {
1405
+ kind: swc_core::common::comments::CommentKind::Block,
1406
+ span: DUMMY_SP,
1407
+ text: text.into(),
1408
+ },
1409
+ );
1410
+ }
1411
+ }
1387
1412
  }
1388
1413
  }
1389
1414
  }
@@ -24,6 +24,9 @@ pub struct VariableVisitor {
24
24
  variables: FxHashMap<Id, Box<Expr>>,
25
25
  imports: FxHashMap<Id, ImportKind>,
26
26
  default_export: Option<ScopedVariableReference>,
27
+ /// Names each local binding is exported as through a local export list
28
+ /// e.g. `export { foo, foo as bar, foo as default }` -> foo#3: [foo, bar, default]
29
+ local_exports: FxHashMap<Id, Vec<Wtf8Atom>>,
27
30
  }
28
31
 
29
32
  #[derive(Debug, Clone, Hash, Eq, PartialEq)]
@@ -67,6 +70,7 @@ impl VariableVisitor {
67
70
  variables: FxHashMap::default(),
68
71
  imports: FxHashMap::default(),
69
72
  default_export: None,
73
+ local_exports: FxHashMap::default(),
70
74
  }
71
75
  }
72
76
 
@@ -157,6 +161,16 @@ impl VariableVisitor {
157
161
  pub fn get_default_export(&self) -> Option<ScopedVariableReference> {
158
162
  self.default_export.clone()
159
163
  }
164
+
165
+ /// Returns the names a local binding is exported as through a local export list
166
+ /// e.g. `export { foo as bar }` -> [bar]
167
+ pub fn get_local_export_names(&self, id: &Id) -> &[Wtf8Atom] {
168
+ self
169
+ .local_exports
170
+ .get(id)
171
+ .map(Vec::as_slice)
172
+ .unwrap_or_default()
173
+ }
160
174
  }
161
175
 
162
176
  impl Fold for VariableVisitor {}
@@ -173,6 +187,31 @@ impl VisitMut for VariableVisitor {
173
187
  }
174
188
  n.visit_mut_children_with(self);
175
189
  }
190
+ /// Scans local export lists (without a `from`) to store the exported names
191
+ /// e.g. `export { foo, foo as bar, foo as default }`
192
+ fn visit_mut_named_export(&mut self, n: &mut NamedExport) {
193
+ if n.src.is_none() {
194
+ for specifier in &n.specifiers {
195
+ if let ExportSpecifier::Named(named) = specifier {
196
+ if let ModuleExportName::Ident(local) = &named.orig {
197
+ let exported: Wtf8Atom = match &named.exported {
198
+ Some(ModuleExportName::Ident(ident)) => ident.sym.clone().into(),
199
+ Some(ModuleExportName::Str(name)) => name.value.clone(),
200
+ None => local.sym.clone().into(),
201
+ #[cfg(swc_ast_unknown)]
202
+ Some(_) => continue,
203
+ };
204
+ self
205
+ .local_exports
206
+ .entry(local.to_id())
207
+ .or_default()
208
+ .push(exported);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ n.visit_mut_children_with(self);
214
+ }
176
215
  /// Scans the AST for variable declarations and extracts the variable names
177
216
  fn visit_mut_var_decl(&mut self, var: &mut VarDecl) {
178
217
  var.decls.iter_mut().for_each(|decl| {
@@ -1,4 +1,5 @@
1
1
  use rustc_hash::FxHashMap;
2
+ use swc_core::atoms::Wtf8Atom;
2
3
  use swc_core::common::util::move_map::MoveMap;
3
4
 
4
5
  use crate::utils::ast_helper::expr_hash_map_to_object;
@@ -53,6 +54,11 @@ pub trait YakTransform {
53
54
  fn get_default_export_comment_prefix(&self) -> Option<String> {
54
55
  None
55
56
  }
57
+ /// Get a comment marker for the current variable exported under another name
58
+ /// through a local export list e.g. `export { foo as bar }` or `export { foo as default }`
59
+ fn get_export_name_comment(&self, _exported_name: &Wtf8Atom, _css_code: &str) -> Option<String> {
60
+ None
61
+ }
56
62
  /// The root class name a compiled styled component carries as the first
57
63
  /// argument of its runtime call - `None` for other transforms
58
64
  /// Used to fold static JSX usages
@@ -306,6 +312,19 @@ impl YakTransform for TransformCssMixin {
306
312
  .join(":"),
307
313
  ))
308
314
  }
315
+
316
+ /// Same marker as for the variable itself, with the first name part replaced by the exported name
317
+ fn get_export_name_comment(&self, exported_name: &Wtf8Atom, css_code: &str) -> Option<String> {
318
+ if !self.is_exported || self.is_within_jsx_attribute {
319
+ return None;
320
+ }
321
+ let name = std::iter::once(exported_name)
322
+ .chain(self.export_name.parts.iter().skip(1))
323
+ .map(|atom| encode_percent(atom.to_string_lossy().as_ref()))
324
+ .collect::<Vec<_>>()
325
+ .join(":");
326
+ Some(format!("YAK EXPORTED MIXIN:{}\n{}\n", name, css_code))
327
+ }
309
328
  }
310
329
 
311
330
  /// Transform styled component api
@@ -552,6 +571,19 @@ impl YakTransform for TransformStyled {
552
571
  self.class_name.clone()
553
572
  ))
554
573
  }
574
+
575
+ /// Marker only (the CSS is already extracted with the variable itself)
576
+ fn get_export_name_comment(&self, exported_name: &Wtf8Atom, _css_code: &str) -> Option<String> {
577
+ if !self.is_exported {
578
+ return None;
579
+ }
580
+ let name = std::iter::once(exported_name)
581
+ .chain(self.declaration_name.parts.iter().skip(1))
582
+ .map(|atom| atom.to_string_lossy())
583
+ .collect::<Vec<_>>()
584
+ .join(".");
585
+ Some(format!("YAK EXPORTED STYLED:{}:{}", name, self.class_name))
586
+ }
555
587
  }
556
588
 
557
589
  /// Transform for global styles
@@ -1,7 +1,7 @@
1
1
  import { styled } from "next-yak/internal";
2
2
  import * as __yak from "next-yak/internal";
3
3
  import "./input.yak.module.css!=!./input?./input.yak.module.css";
4
- const Button = /*YAK Extracted CSS:
4
+ const Button = /*YAK EXPORTED STYLED:Button:input_Button_m7uBBu*//*YAK Extracted CSS:
5
5
  :global(.input_Button_m7uBBu) {
6
6
  background: red;
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import { styled } from "next-yak/internal";
2
2
  import * as __yak from "next-yak/internal";
3
3
  import "./input.yak.module.css!=!./input?./input.yak.module.css";
4
- const Button = /*YAK Extracted CSS:
4
+ const Button = /*YAK EXPORTED STYLED:Button:ym7uBBu*//*YAK Extracted CSS:
5
5
  :global(.ym7uBBu) {
6
6
  background: red;
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import { styled } from "next-yak/internal";
2
2
  import * as __yak from "next-yak/internal";
3
3
  import "data:text/css;base64,LmlucHV0X0J1dHRvbl9tN3VCQnUgewogIGJhY2tncm91bmQ6IHJlZDsKfS5pbnB1dF9UaXRsZV9tN3VCQnUgewogIGNvbG9yOiBibHVlOwogIGZvbnQtc2l6ZTogMjRweDsKfS5pbnB1dF9Db250YWluZXJfbTd1QkJ1IHsKICBwYWRkaW5nOiAyMHB4OwogIGJhY2tncm91bmQ6IHllbGxvdzsKfQ==";
4
- const Button = /*YAK Extracted CSS:
4
+ const Button = /*YAK EXPORTED STYLED:Button:input_Button_m7uBBu*//*YAK Extracted CSS:
5
5
  .input_Button_m7uBBu {
6
6
  background: red;
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import { styled } from "next-yak/internal";
2
2
  import * as __yak from "next-yak/internal";
3
3
  import "data:text/css;base64,LnltN3VCQnUgewogIGJhY2tncm91bmQ6IHJlZDsKfS55bTd1QkJ1MSB7CiAgY29sb3I6IGJsdWU7CiAgZm9udC1zaXplOiAyNHB4Owp9LnltN3VCQnUyIHsKICBwYWRkaW5nOiAyMHB4OwogIGJhY2tncm91bmQ6IHllbGxvdzsKfQ==";
4
- const Button = /*YAK Extracted CSS:
4
+ const Button = /*YAK EXPORTED STYLED:Button:ym7uBBu*//*YAK Extracted CSS:
5
5
  .ym7uBBu {
6
6
  background: red;
7
7
  }
@@ -0,0 +1,11 @@
1
+ import { css, styled } from "next-yak";
2
+
3
+ export { outlined, Title as Heading };
4
+
5
+ const outlined = css`
6
+ outline: 3px solid red;
7
+ `;
8
+
9
+ const Title = styled.h1`
10
+ color: green;
11
+ `;
@@ -0,0 +1,14 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "./input.yak.module.css!=!./input?./input.yak.module.css";
4
+ export { outlined, Title as Heading };
5
+ const outlined = /*YAK EXPORTED MIXIN:outlined
6
+ outline: 3px solid red;
7
+ */ /*#__PURE__*/ css();
8
+ const Title = /*YAK EXPORTED STYLED:Title:input_Title_m7uBBu*//*YAK Extracted CSS:
9
+ :global(.input_Title_m7uBBu) {
10
+ color: green;
11
+ }
12
+ */ /*YAK EXPORTED STYLED:Heading:input_Title_m7uBBu*/ /*#__PURE__*/ Object.assign(/*#__PURE__*/ __yak.__yak_h1("input_Title_m7uBBu"), {
13
+ "displayName": "Title"
14
+ });
@@ -0,0 +1,12 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "./input.yak.module.css!=!./input?./input.yak.module.css";
4
+ export { outlined, Title as Heading };
5
+ const outlined = /*YAK EXPORTED MIXIN:outlined
6
+ outline: 3px solid red;
7
+ */ /*#__PURE__*/ css();
8
+ const Title = /*YAK EXPORTED STYLED:Title:ym7uBBu1*//*YAK Extracted CSS:
9
+ :global(.ym7uBBu1) {
10
+ color: green;
11
+ }
12
+ */ /*YAK EXPORTED STYLED:Heading:ym7uBBu1*/ /*#__PURE__*/ __yak.__yak_h1("ym7uBBu1");
@@ -0,0 +1,14 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "data:text/css;base64,LmlucHV0X1RpdGxlX203dUJCdSB7CiAgY29sb3I6IGdyZWVuOwp9";
4
+ export { outlined, Title as Heading };
5
+ const outlined = /*YAK EXPORTED MIXIN:outlined
6
+ outline: 3px solid red;
7
+ */ /*#__PURE__*/ css();
8
+ const Title = /*YAK EXPORTED STYLED:Title:input_Title_m7uBBu*//*YAK Extracted CSS:
9
+ .input_Title_m7uBBu {
10
+ color: green;
11
+ }
12
+ */ /*YAK EXPORTED STYLED:Heading:input_Title_m7uBBu*/ /*#__PURE__*/ Object.assign(/*#__PURE__*/ __yak.__yak_h1("input_Title_m7uBBu"), {
13
+ "displayName": "Title"
14
+ });
@@ -0,0 +1,12 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "data:text/css;base64,LnltN3VCQnUxIHsKICBjb2xvcjogZ3JlZW47Cn0=";
4
+ export { outlined, Title as Heading };
5
+ const outlined = /*YAK EXPORTED MIXIN:outlined
6
+ outline: 3px solid red;
7
+ */ /*#__PURE__*/ css();
8
+ const Title = /*YAK EXPORTED STYLED:Title:ym7uBBu1*//*YAK Extracted CSS:
9
+ .ym7uBBu1 {
10
+ color: green;
11
+ }
12
+ */ /*YAK EXPORTED STYLED:Heading:ym7uBBu1*/ /*#__PURE__*/ __yak.__yak_h1("ym7uBBu1");
@@ -0,0 +1,15 @@
1
+ import { css, styled } from "next-yak";
2
+
3
+ const outlined = css`
4
+ outline: 3px solid red;
5
+ `;
6
+
7
+ const Title = styled.h1`
8
+ color: green;
9
+ `;
10
+
11
+ const highlighted = css`
12
+ color: blue;
13
+ `;
14
+
15
+ export { outlined, Title, outlined as alias, Title as Heading, highlighted as default };
@@ -0,0 +1,21 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "./input.yak.module.css!=!./input?./input.yak.module.css";
4
+ const outlined = /*YAK EXPORTED MIXIN:outlined
5
+ outline: 3px solid red;
6
+ */ /*YAK EXPORTED MIXIN:alias
7
+ outline: 3px solid red;
8
+ */ /*#__PURE__*/ css();
9
+ const Title = /*YAK EXPORTED STYLED:Title:input_Title_m7uBBu*//*YAK Extracted CSS:
10
+ :global(.input_Title_m7uBBu) {
11
+ color: green;
12
+ }
13
+ */ /*YAK EXPORTED STYLED:Heading:input_Title_m7uBBu*/ /*#__PURE__*/ Object.assign(/*#__PURE__*/ __yak.__yak_h1("input_Title_m7uBBu"), {
14
+ "displayName": "Title"
15
+ });
16
+ const highlighted = /*YAK EXPORTED MIXIN:highlighted
17
+ color: blue;
18
+ */ /*YAK EXPORTED MIXIN:default
19
+ color: blue;
20
+ */ /*#__PURE__*/ css();
21
+ export { outlined, Title, outlined as alias, Title as Heading, highlighted as default };
@@ -0,0 +1,19 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "./input.yak.module.css!=!./input?./input.yak.module.css";
4
+ const outlined = /*YAK EXPORTED MIXIN:outlined
5
+ outline: 3px solid red;
6
+ */ /*YAK EXPORTED MIXIN:alias
7
+ outline: 3px solid red;
8
+ */ /*#__PURE__*/ css();
9
+ const Title = /*YAK EXPORTED STYLED:Title:ym7uBBu1*//*YAK Extracted CSS:
10
+ :global(.ym7uBBu1) {
11
+ color: green;
12
+ }
13
+ */ /*YAK EXPORTED STYLED:Heading:ym7uBBu1*/ /*#__PURE__*/ __yak.__yak_h1("ym7uBBu1");
14
+ const highlighted = /*YAK EXPORTED MIXIN:highlighted
15
+ color: blue;
16
+ */ /*YAK EXPORTED MIXIN:default
17
+ color: blue;
18
+ */ /*#__PURE__*/ css();
19
+ export { outlined, Title, outlined as alias, Title as Heading, highlighted as default };
@@ -0,0 +1,21 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "data:text/css;base64,LmlucHV0X1RpdGxlX203dUJCdSB7CiAgY29sb3I6IGdyZWVuOwp9";
4
+ const outlined = /*YAK EXPORTED MIXIN:outlined
5
+ outline: 3px solid red;
6
+ */ /*YAK EXPORTED MIXIN:alias
7
+ outline: 3px solid red;
8
+ */ /*#__PURE__*/ css();
9
+ const Title = /*YAK EXPORTED STYLED:Title:input_Title_m7uBBu*//*YAK Extracted CSS:
10
+ .input_Title_m7uBBu {
11
+ color: green;
12
+ }
13
+ */ /*YAK EXPORTED STYLED:Heading:input_Title_m7uBBu*/ /*#__PURE__*/ Object.assign(/*#__PURE__*/ __yak.__yak_h1("input_Title_m7uBBu"), {
14
+ "displayName": "Title"
15
+ });
16
+ const highlighted = /*YAK EXPORTED MIXIN:highlighted
17
+ color: blue;
18
+ */ /*YAK EXPORTED MIXIN:default
19
+ color: blue;
20
+ */ /*#__PURE__*/ css();
21
+ export { outlined, Title, outlined as alias, Title as Heading, highlighted as default };
@@ -0,0 +1,19 @@
1
+ import { css, styled } from "next-yak/internal";
2
+ import * as __yak from "next-yak/internal";
3
+ import "data:text/css;base64,LnltN3VCQnUxIHsKICBjb2xvcjogZ3JlZW47Cn0=";
4
+ const outlined = /*YAK EXPORTED MIXIN:outlined
5
+ outline: 3px solid red;
6
+ */ /*YAK EXPORTED MIXIN:alias
7
+ outline: 3px solid red;
8
+ */ /*#__PURE__*/ css();
9
+ const Title = /*YAK EXPORTED STYLED:Title:ym7uBBu1*//*YAK Extracted CSS:
10
+ .ym7uBBu1 {
11
+ color: green;
12
+ }
13
+ */ /*YAK EXPORTED STYLED:Heading:ym7uBBu1*/ /*#__PURE__*/ __yak.__yak_h1("ym7uBBu1");
14
+ const highlighted = /*YAK EXPORTED MIXIN:highlighted
15
+ color: blue;
16
+ */ /*YAK EXPORTED MIXIN:default
17
+ color: blue;
18
+ */ /*#__PURE__*/ css();
19
+ export { outlined, Title, outlined as alias, Title as Heading, highlighted as default };