Skip to content

Commit

Permalink
Allow export const in font loader (#40836)
Browse files Browse the repository at this point in the history
Allow `export const font = Font()` syntax

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
  • Loading branch information
Hannes Bornö committed Sep 23, 2022
1 parent 2e02204 commit 719116a
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 11 deletions.
Expand Up @@ -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<Ident> {
if let Some(decl) = var_decl.decls.get(0) {
let ident = match &decl.name {
Pat::Ident(ident) => Ok(ident.id.clone()),
Expand All @@ -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 => {}
_ => {
Expand All @@ -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| {
Expand All @@ -122,15 +122,45 @@ impl<'a> FontImportsGenerator<'a> {
}
}
}
None
}
}

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,
}),
));
}
}
}
_ => {}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion packages/next-swc/crates/core/src/next_font_loaders/mod.rs
Expand Up @@ -39,6 +39,7 @@ pub struct State {
font_functions: AHashMap<Id, FontFunction>,
removeable_module_items: FxHashSet<BytePos>,
font_imports: Vec<ModuleItem>,
font_exports: Vec<ModuleItem>,
font_functions_in_allowed_scope: FxHashSet<BytePos>,
}

Expand Down Expand Up @@ -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;
}
}
Expand Down
@@ -0,0 +1,5 @@
import React from 'react'
import { Abel, Inter } from '@next/font/google'

export let firaCode = Abel()
export var inter = Inter()
@@ -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 };
@@ -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()
: ^^^^^^^^^^^^^^^^^^^
`----
@@ -1 +1,7 @@
const { a } = Inter({
variant: '400'
});
const [b] = Inter({
variant: '400'
});
const { e } = {};
@@ -0,0 +1,5 @@
import React from 'react'
import { Abel, Inter } from '@next/font/google'

export const firaCode = Abel()
export const inter = Inter()
@@ -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 };
8 changes: 4 additions & 4 deletions test/e2e/next-font/with-font-declarations-file/fonts.js
Expand Up @@ -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 }

0 comments on commit 719116a

Please sign in to comment.