diff --git a/crates/mako/src/plugins/context_module.rs b/crates/mako/src/plugins/context_module.rs index 8acfa2870..94290395d 100644 --- a/crates/mako/src/plugins/context_module.rs +++ b/crates/mako/src/plugins/context_module.rs @@ -1,3 +1,4 @@ +use std::collections::{BTreeMap, HashSet}; use std::fs; use std::path::Path; use std::sync::Arc; @@ -38,25 +39,34 @@ impl Plugin for ContextModulePlugin { let glob_pattern = param.file.pathname.clone().join(glob_pattern); let paths = glob(glob_pattern.to_str().unwrap())?; - let mut key_values = vec![]; + let mut key_values = BTreeMap::new(); + let load_by = if param.file.has_param("async") { + "import" + } else { + "require" + }; for path in paths { let path = path?; let rlt_path = path.strip_prefix(¶m.file.pathname)?; + let is_file = path.is_file(); + + // full path `./i18n/jzh_CN.json` + let mut keys = HashSet::new(); - // full path `./i18n/zh_CN.json` - let mut keys: Vec = vec![]; let metadata = fs::metadata(&path); if let Ok(md) = metadata { if md.is_dir() && !has_index_file_in_directory(&path) { continue; } } - keys.push(format!("./{}", rlt_path.to_string_lossy())); + keys.insert(format!("./{}", rlt_path.to_string_lossy())); // omit ext `./i18n/zh_CN` if let Some(ext) = rlt_path.extension() { - if get_module_extensions().contains(&format!(".{}", ext.to_string_lossy())) { - keys.push(format!( + if is_file + && get_module_extensions().contains(&format!(".{}", ext.to_string_lossy())) + { + keys.insert(format!( "./{}", rlt_path.with_extension("").to_string_lossy() )); @@ -85,16 +95,11 @@ impl Plugin for ContextModulePlugin { } } - let is_async = param.file.has_param("async"); - for key in keys { - let load_by = if is_async { "import" } else { "require" }; - key_values.push(format!( - "'{}': () => {}('{}')", - key, - load_by, - path.to_string_lossy() - )); + let map_entry = + format!("'{}': () => {}('{}')", key, load_by, path.to_string_lossy()); + + key_values.insert(key, map_entry); } } @@ -113,7 +118,10 @@ module.exports = (id) => {{ }} }}; "#, - key_values.join(",\n") + key_values + .into_values() + .collect::>() + .join(",\n") ); Ok(Some(Content::Js(JsContent { content, @@ -245,9 +253,16 @@ fn try_replace_context_arg( } // handle `./foo/${bar}.ext` + // `${bar}` will be handle as `./${bar}` Expr::Tpl(tpl) => { if !tpl.exprs.is_empty() { - let pre_quasis = tpl.quasis.first().unwrap().raw.to_string(); + let first_quasis_str = tpl.quasis.first().unwrap().raw.to_string(); + let pre_quasis = if first_quasis_str.is_empty() { + "./".to_string() + } else { + first_quasis_str + }; + let (prefix, remainder) = if let Some(pos) = pre_quasis.rfind('/') { ( pre_quasis[..=pos].to_string(), diff --git a/e2e/fixtures/javascript.require-dynamic/expect.js b/e2e/fixtures/javascript.context-module/expect.js similarity index 63% rename from e2e/fixtures/javascript.require-dynamic/expect.js rename to e2e/fixtures/javascript.context-module/expect.js index cd05766a2..816f57958 100644 --- a/e2e/fixtures/javascript.require-dynamic/expect.js +++ b/e2e/fixtures/javascript.context-module/expect.js @@ -1,6 +1,6 @@ const assert = require("assert"); -const { parseBuildResult, moduleReg } = require("../../../scripts/test-utils"); -const { files } = parseBuildResult(__dirname); +const {parseBuildResult, moduleReg} = require("../../../scripts/test-utils"); +const {files} = parseBuildResult(__dirname); const names = Object.keys(files); const content = files["index.js"]; @@ -11,26 +11,30 @@ assert.match( moduleReg( "src\\?context&glob=\\*\\*/\\*", [ - "'./ext/json.ts': ()=>__mako_require__(\"src/ext/json.ts\")", - "'./ext/json': ()=>__mako_require__(\"src/ext/json.ts\")", - "'./fake.js': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'./fake': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'./fake.js/a.js': ()=>__mako_require__(\"src/fake.js/a.js\")", - "'./fake.js/a': ()=>__mako_require__(\"src/fake.js/a.js\")", - "'./fake.js/aa.js': ()=>__mako_require__(\"src/fake.js/aa.js\")", - "'./fake.js/aa': ()=>__mako_require__(\"src/fake.js/aa.js\")", - "'./fake.js/index.js': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'./fake.js/index': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'./fake.js': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'./fake.js/': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'./i18n/en-US.json': ()=>__mako_require__(\"src/i18n/en-US.json\")", - "'./i18n/en-US': ()=>__mako_require__(\"src/i18n/en-US.json\")", - "'./i18n/zh-CN.json': ()=>__mako_require__(\"src/i18n/zh-CN.json\")", - "'./i18n/zh-CN': ()=>__mako_require__(\"src/i18n/zh-CN.json\")", - "'./index.ts': ()=>__mako_require__(\"src/index.ts\")", - "'./index': ()=>__mako_require__(\"src/index.ts\")", - "'.': ()=>__mako_require__(\"src/index.ts\")", - "'./': ()=>__mako_require__(\"src/index.ts\")" + `'.': ()=>__mako_require__("src/index.ts")`, + `'./': ()=>__mako_require__("src/index.ts")`, + `'./ext/json': ()=>__mako_require__("src/ext/json.ts")`, + `'./ext/json.ts': ()=>__mako_require__("src/ext/json.ts")`, + `'./fake.js': ()=>__mako_require__("src/fake.js/index.js")`, + `'./fake.js/': ()=>__mako_require__("src/fake.js/index.js")`, + `'./fake.js/a': ()=>__mako_require__("src/fake.js/a.js")`, + `'./fake.js/a.js': ()=>__mako_require__("src/fake.js/a.js")`, + `'./fake.js/aa': ()=>__mako_require__("src/fake.js/aa.js")`, + `'./fake.js/aa.js': ()=>__mako_require__("src/fake.js/aa.js")`, + `'./fake.js/index': ()=>__mako_require__("src/fake.js/index.js")`, + `'./fake.js/index.js': ()=>__mako_require__("src/fake.js/index.js")`, + `'./first_empty_quasis': ()=>__mako_require__("src/first_empty_quasis/index.js")`, + `'./first_empty_quasis/': ()=>__mako_require__("src/first_empty_quasis/index.js")`, + `'./first_empty_quasis/index': ()=>__mako_require__("src/first_empty_quasis/index.js")`, + `'./first_empty_quasis/index.js': ()=>__mako_require__("src/first_empty_quasis/index.js")`, + `'./first_empty_quasis/other': ()=>__mako_require__("src/first_empty_quasis/other.js")`, + `'./first_empty_quasis/other.js': ()=>__mako_require__("src/first_empty_quasis/other.js")`, + `'./i18n/en-US': ()=>__mako_require__("src/i18n/en-US.json")`, + `'./i18n/en-US.json': ()=>__mako_require__("src/i18n/en-US.json")`, + `'./i18n/zh-CN': ()=>__mako_require__("src/i18n/zh-CN.json")`, + `'./i18n/zh-CN.json': ()=>__mako_require__("src/i18n/zh-CN.json")`, + `'./index': ()=>__mako_require__("src/index.ts")`, + `'./index.ts': ()=>__mako_require__("src/index.ts")` ].join(',\n\\s+'), true, ), @@ -42,14 +46,14 @@ assert.match( moduleReg( "src/fake.js\\?context&glob=\\*\\*/\\*", [ - "'./a.js': ()=>__mako_require__(\"src/fake.js/a.js\")", + "'.': ()=>__mako_require__(\"src/fake.js/index.js\")", + "'./': ()=>__mako_require__(\"src/fake.js/index.js\")", "'./a': ()=>__mako_require__(\"src/fake.js/a.js\")", - "'./aa.js': ()=>__mako_require__(\"src/fake.js/aa.js\")", + "'./a.js': ()=>__mako_require__(\"src/fake.js/a.js\")", "'./aa': ()=>__mako_require__(\"src/fake.js/aa.js\")", - "'./index.js': ()=>__mako_require__(\"src/fake.js/index.js\")", + "'./aa.js': ()=>__mako_require__(\"src/fake.js/aa.js\")", "'./index': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'.': ()=>__mako_require__(\"src/fake.js/index.js\")", - "'./': ()=>__mako_require__(\"src/fake.js/index.js\")", + "'./index.js': ()=>__mako_require__(\"src/fake.js/index.js\")", ].join(',\n\\s+'), true, ), @@ -125,3 +129,5 @@ assert.doesNotMatch( /glob=\*\*\/\*\s*\*\//, "should escape glob pattern in module id debug comment" ); + +assert.match(content, /src\/first_empty_quasis\?context&glob=\*\*\/\*&async/g, "should handle template string with first empty quasis"); diff --git a/e2e/fixtures/javascript.require-dynamic/mako.config.json b/e2e/fixtures/javascript.context-module/mako.config.json similarity index 71% rename from e2e/fixtures/javascript.require-dynamic/mako.config.json rename to e2e/fixtures/javascript.context-module/mako.config.json index 885dd937f..ee9362fd5 100644 --- a/e2e/fixtures/javascript.require-dynamic/mako.config.json +++ b/e2e/fixtures/javascript.context-module/mako.config.json @@ -3,5 +3,6 @@ "alias": [ ["@", "./src"] ] - } + }, + "progress":false } diff --git a/e2e/fixtures/javascript.require-dynamic/src/ext/json.ts b/e2e/fixtures/javascript.context-module/src/ext/json.ts similarity index 100% rename from e2e/fixtures/javascript.require-dynamic/src/ext/json.ts rename to e2e/fixtures/javascript.context-module/src/ext/json.ts diff --git a/e2e/fixtures/javascript.require-dynamic/src/fake.js/a.js b/e2e/fixtures/javascript.context-module/src/fake.js/a.js similarity index 100% rename from e2e/fixtures/javascript.require-dynamic/src/fake.js/a.js rename to e2e/fixtures/javascript.context-module/src/fake.js/a.js diff --git a/e2e/fixtures/javascript.require-dynamic/src/fake.js/aa.js b/e2e/fixtures/javascript.context-module/src/fake.js/aa.js similarity index 100% rename from e2e/fixtures/javascript.require-dynamic/src/fake.js/aa.js rename to e2e/fixtures/javascript.context-module/src/fake.js/aa.js diff --git a/e2e/fixtures/javascript.require-dynamic/src/fake.js/index.js b/e2e/fixtures/javascript.context-module/src/fake.js/index.js similarity index 100% rename from e2e/fixtures/javascript.require-dynamic/src/fake.js/index.js rename to e2e/fixtures/javascript.context-module/src/fake.js/index.js diff --git a/e2e/fixtures/javascript.context-module/src/first_empty_quasis/index.js b/e2e/fixtures/javascript.context-module/src/first_empty_quasis/index.js new file mode 100644 index 000000000..4e8640f21 --- /dev/null +++ b/e2e/fixtures/javascript.context-module/src/first_empty_quasis/index.js @@ -0,0 +1,3 @@ +export function loadUrl(url) { + return import(`${url}`) +} diff --git a/e2e/fixtures/javascript.context-module/src/first_empty_quasis/other.js b/e2e/fixtures/javascript.context-module/src/first_empty_quasis/other.js new file mode 100644 index 000000000..a9d961741 --- /dev/null +++ b/e2e/fixtures/javascript.context-module/src/first_empty_quasis/other.js @@ -0,0 +1 @@ +export const other = "other" \ No newline at end of file diff --git a/e2e/fixtures/javascript.require-dynamic/src/i18n/en-US.json b/e2e/fixtures/javascript.context-module/src/i18n/en-US.json similarity index 100% rename from e2e/fixtures/javascript.require-dynamic/src/i18n/en-US.json rename to e2e/fixtures/javascript.context-module/src/i18n/en-US.json diff --git a/e2e/fixtures/javascript.require-dynamic/src/i18n/zh-CN.json b/e2e/fixtures/javascript.context-module/src/i18n/zh-CN.json similarity index 100% rename from e2e/fixtures/javascript.require-dynamic/src/i18n/zh-CN.json rename to e2e/fixtures/javascript.context-module/src/i18n/zh-CN.json diff --git a/e2e/fixtures/javascript.require-dynamic/src/index.ts b/e2e/fixtures/javascript.context-module/src/index.ts similarity index 95% rename from e2e/fixtures/javascript.require-dynamic/src/index.ts rename to e2e/fixtures/javascript.context-module/src/index.ts index 5d3499a22..639bb3b11 100644 --- a/e2e/fixtures/javascript.require-dynamic/src/index.ts +++ b/e2e/fixtures/javascript.context-module/src/index.ts @@ -34,3 +34,4 @@ console.log(loadFile('/zh-CN.json')); console.log(loadFile2('/a.js')); console.log(loadFile3('a.js')); +require("./first_empty_quasis")