diff --git a/packages/next-swc/crates/core/src/next_font_loaders/font_imports_generator.rs b/packages/next-swc/crates/core/src/next_font_loaders/font_imports_generator.rs index e8f8e35030f83..e5721f03bda91 100644 --- a/packages/next-swc/crates/core/src/next_font_loaders/font_imports_generator.rs +++ b/packages/next-swc/crates/core/src/next_font_loaders/font_imports_generator.rs @@ -68,7 +68,7 @@ impl<'a> FontImportsGenerator<'a> { None } - fn check_var_decl(&mut self, var_decl: &VarDecl) { + fn check_var_decl(&mut self, var_decl: &VarDecl) -> Option { if let Some(decl) = var_decl.decls.get(0) { let ident = match &decl.name { Pat::Ident(ident) => Ok(ident.id.clone()), @@ -79,8 +79,6 @@ impl<'a> FontImportsGenerator<'a> { let import_decl = self.check_call_expr(call_expr); if let Some(mut import_decl) = import_decl { - self.state.removeable_module_items.insert(var_decl.span.lo); - match var_decl.kind { VarDeclKind::Const => {} _ => { @@ -100,12 +98,14 @@ impl<'a> FontImportsGenerator<'a> { import_decl.specifiers = vec![ImportSpecifier::Default(ImportDefaultSpecifier { span: DUMMY_SP, - local: ident, + local: ident.clone(), })]; self.state .font_imports .push(ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl))); + + return Some(ident); } Err(pattern) => { HANDLER.with(|handler| { @@ -122,6 +122,7 @@ impl<'a> FontImportsGenerator<'a> { } } } + None } } @@ -129,8 +130,37 @@ impl<'a> Visit for FontImportsGenerator<'a> { noop_visit_type!(); fn visit_module_item(&mut self, item: &ModuleItem) { - if let ModuleItem::Stmt(Stmt::Decl(Decl::Var(var_decl))) = item { - self.check_var_decl(var_decl); + match item { + ModuleItem::Stmt(Stmt::Decl(Decl::Var(var_decl))) => { + if self.check_var_decl(var_decl).is_some() { + self.state.removeable_module_items.insert(var_decl.span.lo); + } + } + ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export_decl)) => { + if let Decl::Var(var_decl) = &export_decl.decl { + if let Some(ident) = self.check_var_decl(var_decl) { + self.state + .removeable_module_items + .insert(export_decl.span.lo); + + self.state.font_exports.push(ModuleItem::ModuleDecl( + ModuleDecl::ExportNamed(NamedExport { + span: DUMMY_SP, + specifiers: vec![ExportSpecifier::Named(ExportNamedSpecifier { + orig: ModuleExportName::Ident(ident), + span: DUMMY_SP, + exported: None, + is_type_only: false, + })], + src: None, + type_only: false, + asserts: None, + }), + )); + } + } + } + _ => {} } } } diff --git a/packages/next-swc/crates/core/src/next_font_loaders/mod.rs b/packages/next-swc/crates/core/src/next_font_loaders/mod.rs index 05457fdd38935..e39e83c69d58a 100644 --- a/packages/next-swc/crates/core/src/next_font_loaders/mod.rs +++ b/packages/next-swc/crates/core/src/next_font_loaders/mod.rs @@ -39,6 +39,7 @@ pub struct State { font_functions: AHashMap, removeable_module_items: FxHashSet, font_imports: Vec, + font_exports: Vec, font_functions_in_allowed_scope: FxHashSet, } @@ -76,10 +77,11 @@ impl VisitMut for NextFontLoaders { // Remove marked module items items.retain(|item| !self.state.removeable_module_items.contains(&item.span_lo())); - // Add font imports + // Add font imports and exports let mut new_items = Vec::new(); new_items.append(&mut self.state.font_imports); new_items.append(items); + new_items.append(&mut self.state.font_exports); *items = new_items; } } diff --git a/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/input.js b/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/input.js new file mode 100644 index 0000000000000..19744c6f8fbed --- /dev/null +++ b/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/input.js @@ -0,0 +1,5 @@ +import React from 'react' +import { Abel, Inter } from '@next/font/google' + +export let firaCode = Abel() +export var inter = Inter() diff --git a/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/output.js b/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/output.js new file mode 100644 index 0000000000000..79c4106ae9fb8 --- /dev/null +++ b/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/output.js @@ -0,0 +1,5 @@ +import firaCode from "@next/font/google?pages/test.tsx;Abel"; +import inter from "@next/font/google?pages/test.tsx;Inter"; +import React from 'react'; +export { firaCode }; +export { inter }; diff --git a/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/output.stderr b/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/output.stderr new file mode 100644 index 0000000000000..184d814d4ee32 --- /dev/null +++ b/packages/next-swc/crates/core/tests/errors/next-font-loaders/export-let/output.stderr @@ -0,0 +1,12 @@ + + x Font loader calls must be assigned to a const + ,-[input.js:4:1] + 4 | export let firaCode = Abel() + : ^^^^^^^^^^^^^^^^^^^^^ + `---- + + x Font loader calls must be assigned to a const + ,-[input.js:5:1] + 5 | export var inter = Inter() + : ^^^^^^^^^^^^^^^^^^^ + `---- diff --git a/packages/next-swc/crates/core/tests/errors/next-font-loaders/not-ident/output.js b/packages/next-swc/crates/core/tests/errors/next-font-loaders/not-ident/output.js index ac0e441683cdc..8fb73367138b0 100644 --- a/packages/next-swc/crates/core/tests/errors/next-font-loaders/not-ident/output.js +++ b/packages/next-swc/crates/core/tests/errors/next-font-loaders/not-ident/output.js @@ -1 +1,7 @@ +const { a } = Inter({ + variant: '400' +}); +const [b] = Inter({ + variant: '400' +}); const { e } = {}; diff --git a/packages/next-swc/crates/core/tests/fixture/next-font-loaders/export-const/input.js b/packages/next-swc/crates/core/tests/fixture/next-font-loaders/export-const/input.js new file mode 100644 index 0000000000000..b6eeca9fed307 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/next-font-loaders/export-const/input.js @@ -0,0 +1,5 @@ +import React from 'react' +import { Abel, Inter } from '@next/font/google' + +export const firaCode = Abel() +export const inter = Inter() diff --git a/packages/next-swc/crates/core/tests/fixture/next-font-loaders/export-const/output.js b/packages/next-swc/crates/core/tests/fixture/next-font-loaders/export-const/output.js new file mode 100644 index 0000000000000..79c4106ae9fb8 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/next-font-loaders/export-const/output.js @@ -0,0 +1,5 @@ +import firaCode from "@next/font/google?pages/test.tsx;Abel"; +import inter from "@next/font/google?pages/test.tsx;Inter"; +import React from 'react'; +export { firaCode }; +export { inter }; diff --git a/test/e2e/next-font/with-font-declarations-file/fonts.js b/test/e2e/next-font/with-font-declarations-file/fonts.js index d4785f5c39316..aa0c1ac0e2ebc 100644 --- a/test/e2e/next-font/with-font-declarations-file/fonts.js +++ b/test/e2e/next-font/with-font-declarations-file/fonts.js @@ -11,11 +11,11 @@ const openSans = Open_Sans() const sourceCodePro = Source_Code_Pro({ display: 'swap', preload: false }) const abel = Abel({ variant: '400', display: 'optional', preload: false }) -const inter = Inter({ display: 'block', preload: true }) -const roboto = Roboto({ variant: '400' }) +export const inter = Inter({ display: 'block', preload: true }) +export const roboto = Roboto({ variant: '400' }) -const myLocalFont = localFont({ +export const myLocalFont = localFont({ src: './my-font.woff2', }) -export { openSans, sourceCodePro, abel, inter, roboto, myLocalFont } +export { openSans, sourceCodePro, abel }