Skip to content

Commit b808695

Browse files
authored
css modules: use a terser selector format that requires less escaping (#3437)
Fixes WEB-447. Previously, generated classnames would include literal `/` characters, which need escaping when generating selectors. While users should still escape selectors, this avoids it for this case and makes generated code easier to read. This format is also more aligned with what webpack-based css modules generates. This also removes the square character as a separator, since it breaks words and makes double-clicking for selection more difficult.
1 parent dd11273 commit b808695

13 files changed

+36
-20
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/next-dev-tests/tests/integration/next/font-google/basic/pages/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ export default function Home() {
1818
function runTests() {
1919
it("returns structured data about the font styles from the font function", () => {
2020
expect(interNoArgs).toEqual({
21-
className:
22-
"className◽[project-with-next]/crates/next-dev-tests/tests/integration/next/font-google/basic/[embedded_modules]/@vercel/turbopack-next/internal/font/google/inter_34ab8b4d.module.css",
21+
className: "className__inter_34ab8b4d__77c0d301",
2322
style: {
2423
fontFamily: "'__Inter_34ab8b4d'",
2524
fontStyle: "normal",

crates/turbopack-css/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ bench = false
1313
anyhow = "1.0.47"
1414
async-trait = "0.1.56"
1515
indexmap = { workspace = true }
16+
once_cell = "1.13.0"
17+
regex = "1.6.0"
1618
serde = "1.0.136"
17-
1819
turbo-tasks = { path = "../turbo-tasks" }
1920
turbo-tasks-fs = { path = "../turbo-tasks-fs" }
2021
turbo-tasks-hash = { path = "../turbo-tasks-hash" }

crates/turbopack-css/src/parse.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::sync::Arc;
22

3-
use anyhow::Result;
3+
use anyhow::{Context, Result};
44
use indexmap::IndexMap;
5+
use once_cell::sync::Lazy;
6+
use regex::Regex;
57
use swc_core::{
68
common::{
79
errors::Handler, source_map::SourceMapGenConfig, BytePos, FileName, LineCol, SourceMap,
@@ -26,6 +28,9 @@ use crate::{
2628
CssModuleAssetType,
2729
};
2830

31+
// Capture up until the first "."
32+
static BASENAME_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[^.]*").unwrap());
33+
2934
#[turbo_tasks::value(shared, serialization = "none", eq = "manual")]
3035
pub enum ParseResult {
3136
Ok {
@@ -201,15 +206,19 @@ async fn parse_content(
201206
CssModuleAssetType::Global => Default::default(),
202207
CssModuleAssetType::Module => {
203208
let imports = swc_core::css::modules::imports::analyze_imports(&parsed_stylesheet);
209+
let basename = BASENAME_RE
210+
.captures(fs_path.file_name())
211+
.context("Must include basename preceding .")?
212+
.get(0)
213+
.context("Must include basename preceding .")?
214+
.as_str();
215+
// Truncate this as u32 so it's formated as 8-character hex in the suffic below
216+
let path_hash = turbo_tasks_hash::hash_xxh3_hash64(fs_path_str) as u32;
204217
let result = swc_core::css::modules::compile(
205218
&mut parsed_stylesheet,
206219
// TODO swc_css_modules should take `impl TransformConfig + '_`
207220
ModuleTransformConfig {
208-
// Note this uses an square emoji to join class name with module name
209-
// This emoji is usually not used in css class names so it's easy for the user
210-
// to see which class names are generated by css modules. Its also a pretty
211-
// small, so it's not too intense for the eyes.
212-
suffix: format!("◽{}", fs_path_str),
221+
suffix: format!("__{}__{:x}", basename, path_hash),
213222
},
214223
);
215224
let mut exports = result.renamed.into_iter().collect::<IndexMap<_, _>>();

crates/turbopack-tests/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,8 @@ turbopack-env = { path = "../turbopack-env" }
3131

3232
[build-dependencies]
3333
turbo-tasks-build = { path = "../turbo-tasks-build" }
34+
35+
[features]
36+
default = ["native-tls"]
37+
native-tls = ["next-core/native-tls"]
38+
rustls-tls = ["next-core/rustls-tls"]

crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_907a50.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)