-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(rust-plugins): 💡 refactor yaml plugin (#92)
- Loading branch information
Showing
3 changed files
with
121 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
# @farmfe/plugin-yaml | ||
|
||
## 0.0.8 | ||
|
||
### Patch Changes | ||
|
||
- refactor yaml plugin | ||
|
||
## 0.0.7 | ||
|
||
### Patch Changes | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,130 +1,155 @@ | ||
#![deny(clippy::all)] | ||
|
||
use farmfe_core::{config::Config, module::ModuleType, plugin::Plugin, serde_json}; | ||
use farmfe_core::{ | ||
config::Config, | ||
module::ModuleType, | ||
plugin::{Plugin, PluginLoadHookParam, PluginLoadHookResult, PluginTransformHookParam, PluginTransformHookResult}, | ||
serde_json | ||
}; | ||
use farmfe_macro_plugin::farm_plugin; | ||
use lazy_static::lazy_static; | ||
use regex::Regex; | ||
use serde::Deserialize; | ||
use std::fs::read_to_string; | ||
|
||
lazy_static! { | ||
static ref YAML_MODULE_TYPE: String = String::from("yaml"); | ||
static ref YAML_MODULE_TYPE: String = String::from("yaml"); | ||
} | ||
|
||
/// 检查文件是否为 YAML 文件 | ||
fn is_yaml_file(file_name: &String) -> bool { | ||
file_name.ends_with(".yaml") || file_name.ends_with(".yml") | ||
file_name.ends_with(".yaml") || file_name.ends_with(".yml") | ||
} | ||
|
||
/// YAML 文档解析模式 | ||
#[derive(Debug, Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
enum DocumentMode { | ||
Single, | ||
Multi | ||
/// 单文档模式 | ||
Single, | ||
/// 多文档模式 | ||
Multi | ||
} | ||
|
||
/// YAML 插件配置选项 | ||
#[derive(Debug, Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct FarmPluginYamlOptions { | ||
document_mode: Option<DocumentMode>, | ||
include: Option<String>, | ||
exclude: Option<String>, | ||
document_mode: Option<DocumentMode>, | ||
include: Option<String>, | ||
exclude: Option<String>, | ||
} | ||
|
||
/// Farm YAML 插件 | ||
#[farm_plugin] | ||
pub struct FarmPluginYaml { | ||
document_mode: DocumentMode, | ||
include: String, | ||
exclude: String, | ||
document_mode: DocumentMode, | ||
include: String, | ||
exclude: String, | ||
} | ||
|
||
impl FarmPluginYaml { | ||
fn new(_config: &Config, options: String) -> Self { | ||
let yaml_options: FarmPluginYamlOptions = serde_json::from_str(&options).unwrap(); | ||
let include: String = yaml_options.include.unwrap_or(String::from("")); | ||
let exclude: String = yaml_options.exclude.unwrap_or(String::from("")); | ||
Self { | ||
document_mode: yaml_options.document_mode.unwrap_or(DocumentMode::Single), | ||
include, | ||
exclude, | ||
fn new(_config: &Config, options: String) -> Self { | ||
let yaml_options: FarmPluginYamlOptions = serde_json::from_str(&options) | ||
.expect("Failed to parse YAML plugin options"); | ||
let include: String = yaml_options.include.unwrap_or_default(); | ||
let exclude: String = yaml_options.exclude.unwrap_or_default(); | ||
Self { | ||
document_mode: yaml_options.document_mode.unwrap_or(DocumentMode::Single), | ||
include, | ||
exclude, | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl Plugin for FarmPluginYaml { | ||
fn name(&self) -> &str { | ||
"FarmPluginYaml" | ||
} | ||
fn load( | ||
&self, | ||
param: &farmfe_core::plugin::PluginLoadHookParam, | ||
_context: &std::sync::Arc<farmfe_core::context::CompilationContext>, | ||
_hook_context: &farmfe_core::plugin::PluginHookContext, | ||
) -> farmfe_core::error::Result<Option<farmfe_core::plugin::PluginLoadHookResult>> { | ||
if is_yaml_file(¶m.module_id) { | ||
let content = read_to_string(param.resolved_path).unwrap(); | ||
return Ok(Some(farmfe_core::plugin::PluginLoadHookResult { | ||
content, | ||
source_map: None, | ||
module_type: ModuleType::Custom(YAML_MODULE_TYPE.to_string()), | ||
})); | ||
} | ||
Ok(None) | ||
} | ||
fn transform( | ||
&self, | ||
param: &farmfe_core::plugin::PluginTransformHookParam, | ||
_context: &std::sync::Arc<farmfe_core::context::CompilationContext>, | ||
) -> farmfe_core::error::Result<Option<farmfe_core::plugin::PluginTransformHookResult>> { | ||
if param.module_type != ModuleType::Custom(YAML_MODULE_TYPE.to_string()) { | ||
return Ok(None); | ||
/// 检查是否应处理指定路径 | ||
fn should_process_path(&self, path: &str) -> bool { | ||
if !self.include.is_empty() { | ||
let inc_reg = match Regex::new(&self.include) { | ||
Ok(reg) => reg, | ||
Err(_) => return false, | ||
}; | ||
if inc_reg.find(path).is_none() { | ||
return false; | ||
} | ||
} | ||
|
||
if !self.exclude.is_empty() { | ||
let exc_reg = match Regex::new(&self.exclude) { | ||
Ok(reg) => reg, | ||
Err(_) => return true, | ||
}; | ||
if exc_reg.find(path).is_some() { | ||
return false; | ||
} | ||
} | ||
|
||
true | ||
} | ||
|
||
if !self.include.is_empty() { | ||
let inc_reg = Regex::new(&format!("{}", self.include)).unwrap(); | ||
if let Some(_text) = inc_reg.find(param.resolved_path) { | ||
} else { | ||
return Ok(None); | ||
} | ||
/// 将 YAML 内容转换为 JavaScript 导出 | ||
fn yaml_to_js(&self, content: &str) -> Result<String, Box<dyn std::error::Error>> { | ||
let result = match self.document_mode { | ||
DocumentMode::Single | DocumentMode::Multi => { | ||
serde_yaml::from_str::<serde_json::Value>(content)? | ||
} | ||
}; | ||
|
||
let mut export_val = String::new(); | ||
if let serde_json::Value::Object(object) = result.clone() { | ||
for (key, val) in object { | ||
export_val.push_str(&format!("export var {} = {};\n", key, val)); | ||
} | ||
} | ||
|
||
Ok(format!("export default {};\n\n{}", result, export_val)) | ||
} | ||
} | ||
|
||
if !self.exclude.is_empty() { | ||
let exc_reg = Regex::new(&format!("{}", self.exclude)).unwrap(); | ||
if let Some(_text) = exc_reg.find(param.resolved_path) { | ||
return Ok(None); | ||
} | ||
impl Plugin for FarmPluginYaml { | ||
fn name(&self) -> &str { | ||
"FarmPluginYaml" | ||
} | ||
|
||
let code = match self.document_mode { | ||
DocumentMode::Single => { | ||
let result: serde_json::Value = | ||
serde_yaml::from_str::<serde_json::Value>(¶m.content).unwrap(); | ||
let mut export_val = String::new(); | ||
fn load( | ||
&self, | ||
param: &PluginLoadHookParam, | ||
_context: &std::sync::Arc<farmfe_core::context::CompilationContext>, | ||
_hook_context: &farmfe_core::plugin::PluginHookContext, | ||
) -> farmfe_core::error::Result<Option<PluginLoadHookResult>> { | ||
if is_yaml_file(¶m.module_id) { | ||
let content = read_to_string(param.resolved_path).unwrap(); | ||
return Ok(Some(PluginLoadHookResult { | ||
content, | ||
source_map: None, | ||
module_type: ModuleType::Custom(YAML_MODULE_TYPE.to_string()), | ||
})); | ||
} | ||
Ok(None) | ||
} | ||
|
||
if let serde_json::Value::Object(object) = result.clone() { | ||
for (key, val) in object { | ||
export_val.push_str(&format!("export var {} = {};\n", key, val)); | ||
} | ||
fn transform( | ||
&self, | ||
param: &PluginTransformHookParam, | ||
_context: &std::sync::Arc<farmfe_core::context::CompilationContext>, | ||
) -> farmfe_core::error::Result<Option<PluginTransformHookResult>> { | ||
if param.module_type != ModuleType::Custom(YAML_MODULE_TYPE.to_string()) { | ||
return Ok(None); | ||
} | ||
format!("export default {}\n\n {}", result, export_val) | ||
} | ||
DocumentMode::Multi => { | ||
let result: serde_json::Value = | ||
serde_yaml::from_str::<serde_json::Value>(¶m.content).unwrap(); | ||
let mut export_val = String::new(); | ||
if let serde_json::Value::Object(object) = result.clone() { | ||
for (key, val) in object { | ||
export_val.push_str(&format!("export var {} = {};\n", key, val)); | ||
} | ||
|
||
if !self.should_process_path(param.resolved_path) { | ||
return Ok(None); | ||
} | ||
format!("export default {}\n\n {}", result, export_val) | ||
} | ||
}; | ||
|
||
return Ok(Some(farmfe_core::plugin::PluginTransformHookResult { | ||
content: code, | ||
module_type: Some(ModuleType::Js), | ||
source_map: None, | ||
ignore_previous_source_map: false, | ||
})); | ||
} | ||
|
||
let code = match self.yaml_to_js(¶m.content) { | ||
Ok(code) => code, | ||
Err(e) => panic!("Failed to parse YAML: {}", e), | ||
}; | ||
|
||
Ok(Some(PluginTransformHookResult { | ||
content: code, | ||
module_type: Some(ModuleType::Js), | ||
source_map: None, | ||
ignore_previous_source_map: false, | ||
})) | ||
} | ||
} |