Skip to content

Commit

Permalink
feat: support emit_file
Browse files Browse the repository at this point in the history
  • Loading branch information
sorrycc committed Dec 24, 2024
1 parent 842ec61 commit 539ea95
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 28 deletions.
87 changes: 66 additions & 21 deletions crates/binding/src/js_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ fn content_from_result(result: TransformResult) -> Result<Content> {
}

#[napi]
pub struct PluginContext {}
pub struct PluginContext {
context: Arc<Context>,
}

#[napi]
impl PluginContext {
Expand All @@ -41,6 +43,12 @@ impl PluginContext {
pub fn error(&self, msg: String) {
println!("ERROR: {}", msg)
}
#[napi]
pub fn emit_file(&self, origin_path: String, output_path: String) {
let mut assets_info = self.context.assets_info.lock().unwrap();
assets_info.insert(origin_path, output_path);
drop(assets_info);
}
}

pub struct JsPlugin {
Expand All @@ -58,25 +66,31 @@ impl Plugin for JsPlugin {
self.enforce.as_deref()
}

fn build_start(&self, _context: &Arc<Context>) -> Result<()> {
fn build_start(&self, context: &Arc<Context>) -> Result<()> {
if let Some(hook) = &self.hooks.build_start {
hook.call(PluginContext {})?
hook.call(PluginContext {
context: context.clone(),
})?
}
Ok(())
}

fn load(&self, param: &PluginLoadParam, _context: &Arc<Context>) -> Result<Option<Content>> {
fn load(&self, param: &PluginLoadParam, context: &Arc<Context>) -> Result<Option<Content>> {
if let Some(hook) = &self.hooks.load {
if self.hooks.load_include.is_some()
&& self.hooks.load_include.as_ref().unwrap().call((
PluginContext {},
PluginContext {
context: context.clone(),
},
param.file.path.to_string_lossy().to_string(),
))? == Some(false)
{
return Ok(None);
}
let x: Option<LoadResult> = hook.call((
PluginContext {},
PluginContext {
context: context.clone(),
},
param.file.path.to_string_lossy().to_string(),
))?;
if let Some(x) = x {
Expand All @@ -95,11 +109,13 @@ impl Plugin for JsPlugin {
source: &str,
importer: &str,
params: &PluginResolveIdParams,
_context: &Arc<Context>,
context: &Arc<Context>,
) -> Result<Option<ResolverResource>> {
if let Some(hook) = &self.hooks.resolve_id {
let x: Option<ResolveIdResult> = hook.call((
PluginContext {},
PluginContext {
context: context.clone(),
},
source.to_string(),
importer.to_string(),
ResolveIdParams {
Expand Down Expand Up @@ -127,22 +143,31 @@ impl Plugin for JsPlugin {
Ok(None)
}

fn generate_end(&self, param: &PluginGenerateEndParams, _context: &Arc<Context>) -> Result<()> {
fn generate_end(&self, param: &PluginGenerateEndParams, context: &Arc<Context>) -> Result<()> {
// keep generate_end for compatibility
// since build_end does not have none error params in unplugin's api spec
if let Some(hook) = &self.hooks.generate_end {
hook.call((PluginContext {}, serde_json::to_value(param)?))?
hook.call((
PluginContext {
context: context.clone(),
},
serde_json::to_value(param)?,
))?
}
if let Some(hook) = &self.hooks.build_end {
hook.call(PluginContext {})?
hook.call(PluginContext {
context: context.clone(),
})?
}
Ok(())
}

fn watch_changes(&self, id: &str, event: &str, _context: &Arc<Context>) -> Result<()> {
fn watch_changes(&self, id: &str, event: &str, context: &Arc<Context>) -> Result<()> {
if let Some(hook) = &self.hooks.watch_changes {
hook.call((
PluginContext {},
PluginContext {
context: context.clone(),
},
id.to_string(),
WatchChangesParams {
event: event.to_string(),
Expand All @@ -152,17 +177,26 @@ impl Plugin for JsPlugin {
Ok(())
}

fn write_bundle(&self, _context: &Arc<Context>) -> Result<()> {
fn write_bundle(&self, context: &Arc<Context>) -> Result<()> {
if let Some(hook) = &self.hooks.write_bundle {
hook.call(PluginContext {})?
hook.call(PluginContext {
context: context.clone(),
})?
}
Ok(())
}

fn before_write_fs(&self, path: &std::path::Path, content: &[u8]) -> Result<()> {
fn before_write_fs(
&self,
path: &std::path::Path,
content: &[u8],
context: &Arc<Context>,
) -> Result<()> {
if let Some(hook) = &self.hooks._on_generate_file {
hook.call((
PluginContext {},
PluginContext {
context: context.clone(),
},
WriteFile {
path: path.to_string_lossy().to_string(),
content: content.to_vec(),
Expand All @@ -176,10 +210,16 @@ impl Plugin for JsPlugin {
&self,
content: &mut Content,
path: &str,
_context: &Arc<Context>,
context: &Arc<Context>,
) -> Result<Option<Content>> {
if let Some(hook) = &self.hooks.transform_include {
if hook.call((PluginContext {}, path.to_string()))? == Some(false) {
if hook.call((
PluginContext {
context: context.clone(),
},
path.to_string(),
))? == Some(false)
{
return Ok(None);
}
}
Expand All @@ -191,8 +231,13 @@ impl Plugin for JsPlugin {
_ => return Ok(None),
};

let result: Option<TransformResult> =
hook.call((PluginContext {}, content_str, path.to_string()))?;
let result: Option<TransformResult> = hook.call((
PluginContext {
context: context.clone(),
},
content_str,
path.to_string(),
))?;

if let Some(result) = result {
return content_from_result(result).map(Some);
Expand Down
10 changes: 8 additions & 2 deletions crates/mako/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,12 @@ pub trait Plugin: Any + Send + Sync {
Ok(())
}

fn before_write_fs(&self, _path: &Path, _content: &[u8]) -> Result<()> {
fn before_write_fs(
&self,
_path: &Path,
_content: &[u8],
_context: &Arc<Context>,
) -> Result<()> {
Ok(())
}

Expand Down Expand Up @@ -422,9 +427,10 @@ impl PluginDriver {
&self,
path: P,
content: C,
context: &Arc<Context>,
) -> Result<()> {
for p in &self.plugins {
p.before_write_fs(path.as_ref(), content.as_ref())?;
p.before_write_fs(path.as_ref(), content.as_ref(), context)?;
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/mako/src/plugins/bundless_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl BundlessCompiler {

self.context
.plugin_driver
.before_write_fs(&to, content.as_ref())
.before_write_fs(&to, content.as_ref(), &self.context)
.unwrap();

if !self.context.config.output.skip_write {
Expand Down
4 changes: 4 additions & 0 deletions e2e/fixtures/plugins.context/plugins.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ module.exports = [
message: 'test warn with object',
});
this.error('error: ' + path);
this.emitFile({
fileName: 'test.txt',
source: 'test',
});
return {
content: `export default () => <Foooo>.hoo</Foooo>;`,
type: 'jsx',
Expand Down
1 change: 1 addition & 0 deletions packages/mako/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,5 @@ export declare function build(buildParams: BuildParams): Promise<void>;
export class PluginContext {
warn(msg: string): void;
error(msg: string): void;
emitFile(originPath: string, outputPath: string): void;
}
21 changes: 21 additions & 0 deletions packages/mako/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from 'fs';
import os from 'os';
import path from 'path';
import { omit } from 'lodash';
import resolve from 'resolve';
Expand Down Expand Up @@ -194,6 +195,26 @@ export async function build(params: BuildParams) {
plugin[key] = (context: any, ...args: any[]) => {
return oldValue.apply(
{
emitFile(file: {
name?: string;
fileName?: string;
source?: string | Uint8Array;
}) {
if (file.name && !file.fileName) {
throw new Error(
'name in emitFile is not supported yet, please supply fileName instead',
);
}
// Since assets_info in mako is a <origin_path, output_path> map,
// we need to generate a tmp file to store the content, and then emit it
// TODO: we should use a better way to handle this
const tmpFile = path.join(
os.tmpdir(),
Math.random().toString(36).substring(2, 15),
);
fs.writeFileSync(tmpFile, file.source!);
context.emitFile(tmpFile, file.fileName!);
},
warn(
message:
| string
Expand Down
12 changes: 8 additions & 4 deletions scripts/mako.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ build({
root: cwd,
config,
watch: process.argv.includes('--watch'),
}).catch((e) => {
console.error(e);
process.exit(1);
});
})
.then(() => {
process.exit(0);
})
.catch((e) => {
console.error(e);
process.exit(1);
});

function getPlugins() {
let plugins = [];
Expand Down

0 comments on commit 539ea95

Please sign in to comment.