Skip to content

Commit

Permalink
feat; support css module name coversion
Browse files Browse the repository at this point in the history
  • Loading branch information
shulandmimi committed Sep 18, 2024
1 parent 5f0c02d commit c6d6828
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/weak-dogs-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@farmfe/core": patch
---

support css module name coversion
46 changes: 46 additions & 0 deletions crates/core/src/config/css.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use heck::{ToLowerCamelCase, ToSnakeCase, ToUpperCamelCase};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub enum NameConversion {
///
/// to keep the original name
///
#[default]
#[serde(rename = "asIs")]
AsIs,
///
/// ```md
/// "It is we who built these palaces and cities."
/// // =>
/// "itIsWeWhoBuiltThesePalacesAndCities"
/// ```
#[serde(rename = "lowerCamel")]
LowerCamel,
/// ```md
/// "We are not in the least afraid of ruins."
/// // =>
/// "WeAreNotInTheLeastAfraidOfRuins"
/// ```
#[serde(rename = "upperCamel")]
UpperCamel,

/// ```md
/// "We carry a new world here, in our hearts."
/// // =>
/// "we_carry_a_new_world_here_in_our_hearts"
/// ```
#[serde(rename = "snake")]
Snake,
}

impl NameConversion {
pub fn transform(&self, name: &str) -> String {
match self {
NameConversion::LowerCamel => name.to_lower_camel_case(),
NameConversion::UpperCamel => name.to_upper_camel_case(),
NameConversion::Snake => name.to_snake_case(),
NameConversion::AsIs => name.to_string(),
}
}
}
13 changes: 13 additions & 0 deletions crates/core/src/config/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ use crate::context::CompilationContext;

use super::{
config_regex::ConfigRegex,
css::NameConversion,
external::{ExternalConfig, ExternalObject},
Config,
};

const CUSTOM_CONFIG_RUNTIME_ISOLATE: &str = "runtime.isolate";
pub const CUSTOM_CONFIG_EXTERNAL_RECORD: &str = "external.record";
pub const CUSTOM_CONFIG_RESOLVE_DEDUPE: &str = "resolve.dedupe";
pub const CUSTOM_CONFIG_CSS_MODULES_LOCAL_CONVERSION: &str = "css.modules.locals_conversion";

pub fn get_config_runtime_isolate(context: &Arc<CompilationContext>) -> bool {
if let Some(val) = context.config.custom.get(CUSTOM_CONFIG_RUNTIME_ISOLATE) {
Expand Down Expand Up @@ -54,3 +56,14 @@ pub fn get_config_resolve_dedupe(config: &Config) -> Vec<String> {
vec![]
}
}

pub fn get_config_css_modules_local_conversion(config: &Config) -> NameConversion {
if let Some(val) = config
.custom
.get(CUSTOM_CONFIG_CSS_MODULES_LOCAL_CONVERSION)
{
serde_json::from_str(val).unwrap_or_default()
} else {
Default::default()
}
}
1 change: 1 addition & 0 deletions crates/core/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub const FARM_MODULE_EXPORT: &str = "exports";
pub mod bool_or_obj;
pub mod comments;
pub mod config_regex;
pub mod css;
pub mod custom;
pub mod external;
pub mod html;
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub use swc_ecma_ast;
pub use swc_ecma_parser;
pub use swc_html_ast;
pub use wax;
pub use heck;

#[macro_export]
macro_rules! farm_profile_scope {
Expand Down
13 changes: 11 additions & 2 deletions crates/plugin_css/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::collections::HashMap;
use std::{path::PathBuf, sync::Arc};

use dep_analyzer::DepAnalyzer;
use farmfe_core::config::css::NameConversion;
use farmfe_core::config::custom::get_config_css_modules_local_conversion;
use farmfe_core::config::minify::MinifyOptions;
use farmfe_core::module::CommentsMetaData;
use farmfe_core::{
Expand Down Expand Up @@ -171,6 +173,7 @@ pub struct FarmPluginCss {
ast_map: Mutex<HashMap<String, (Stylesheet, CommentsMetaData)>>,
content_map: Mutex<HashMap<String, String>>,
sourcemap_map: Mutex<HashMap<String, String>>,
locals_conversion: NameConversion,
}

fn prefixer(stylesheet: &mut Stylesheet, css_prefixer_config: &CssPrefixerConfig) {
Expand All @@ -184,6 +187,7 @@ impl Plugin for FarmPluginCss {
fn name(&self) -> &str {
"FarmPluginCss"
}

/// This plugin should be executed at last
fn priority(&self) -> i32 {
-99
Expand Down Expand Up @@ -336,10 +340,14 @@ impl Plugin for FarmPluginCss {
}
}
}
export_names.push((name, after_transform_classes));

export_names.push((
self.locals_conversion.transform(&name),
after_transform_classes,
));
}

export_names.sort_by_key(|e| e.0);
export_names.sort_by_key(|e| e.0.to_string());

let code = format!(
r#"
Expand Down Expand Up @@ -764,6 +772,7 @@ impl FarmPluginCss {
ast_map: Mutex::new(Default::default()),
content_map: Mutex::new(Default::default()),
sourcemap_map: Mutex::new(Default::default()),
locals_conversion: get_config_css_modules_local_conversion(config),
}
}

Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"concurrentify",
"Consolas",
"consts",
"Convertion",
"cpus",
"csspart",
"ctxt",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export const FARM_DEFAULT_NAMESPACE = 'FARM_DEFAULT_NAMESPACE';
export const CUSTOM_KEYS = {
external_record: 'external.record',
runtime_isolate: 'runtime.isolate',
resolve_dedupe: 'resolve.dedupe'
resolve_dedupe: 'resolve.dedupe',
css_locals_conversion: 'css.modules.locals_conversion'
};

export const FARM_RUST_PLUGIN_FUNCTION_ENTRY = 'func.js';
2 changes: 2 additions & 0 deletions packages/core/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import {
FARM_DEFAULT_NAMESPACE
} from './constants.js';
import { mergeConfig, mergeFarmCliConfig } from './mergeConfig.js';
import { normalizeCss } from './normalize-config/normalize-css.js';
import { normalizeExternal } from './normalize-config/normalize-external.js';
import { normalizeResolve } from './normalize-config/normalize-resolve.js';
import type {
Expand Down Expand Up @@ -558,6 +559,7 @@ export async function normalizeUserCompilationConfig(
);

normalizeResolve(userConfig, resolvedCompilation);
normalizeCss(userConfig, resolvedCompilation);

return resolvedCompilation;
}
Expand Down
26 changes: 26 additions & 0 deletions packages/core/src/config/normalize-config/normalize-css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { CUSTOM_KEYS } from '../constants.js';
import { ResolvedCompilation, UserConfig } from '../types.js';

export function normalizeCss(
config: UserConfig,
resolvedCompilation: ResolvedCompilation
) {
if (config.compilation?.css?.modules) {
normalizeCssModules(config, resolvedCompilation);
}
}

function normalizeCssModules(
config: UserConfig,
resolvedCompilation: ResolvedCompilation
) {
if (config.compilation.css.modules.localsConversion) {
const localsConvention = config.compilation.css.modules.localsConversion;
delete resolvedCompilation.css.modules.localsConversion;
if (typeof localsConvention === 'string') {
resolvedCompilation.custom[CUSTOM_KEYS.css_locals_conversion] =
JSON.stringify(localsConvention);
}
}
console.log(resolvedCompilation.custom);
}
4 changes: 3 additions & 1 deletion packages/core/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,9 @@ const compilationConfigSchema = z
.union([
z.null(),
z.object({
indentName: z.string().optional()
indentName: z.string().optional(),
localsConversion: z.string().optional(),
paths: z.array(z.string()).optional()
})
])

Expand Down
9 changes: 8 additions & 1 deletion packages/core/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { Options } from 'http-proxy-middleware';
import { Middleware } from 'koa';
import type { RustPlugin } from '../plugin/rust/index.js';
import type { JsPlugin } from '../plugin/type.js';
import type { Config } from '../types/binding.js';
import type { Config, CssConfig } from '../types/binding.js';
import type { Logger } from '../utils/index.js';

export interface ConfigEnv {
Expand Down Expand Up @@ -108,13 +108,20 @@ export interface UserConfig {
/** Files under this dir will always be treated as static assets. serve it in dev, and copy it to output.path when build */
}

interface ResolvedCss extends CssConfig {
modules?: CssConfig['modules'] & {
localsConversion?: never;
};
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ResolvedCompilation
extends Exclude<Config['config'], undefined> {
external?: string[];
resolve?: {
dedupe?: never;
} & Config['config']['resolve'];
css?: ResolvedCss;
}

export interface ResolvedUserConfig extends UserConfig {
Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/types/binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,16 @@ export interface CssConfig {
paths?: string[];
// configure the generated css class name, the default is `[name]-[hash]`
indentName?: string;
/**
*
* - `asIs` - Do not convert the local variable name
* - `lowerCamel` - Convert the local variable name to lower camel case e.g: `fooBar`
* - `upperCamel` - Convert the local variable name to upper camel case e.g: `FooBar`
* - `snake` - Convert the local variable name to snake case e.g: `foo_bar`
*
* @default 'asIs'
*/
localsConversion?: 'asIs' | 'lowerCamel' | 'upperCamel' | 'snake';
} | null;
/**
* Configure CSS compatibility prefixes, such as -webkit-.
Expand Down

0 comments on commit c6d6828

Please sign in to comment.