Skip to content

Commit

Permalink
refactor(rust-plugins): 💡 refactor yaml plugin (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
Maidang1 authored Nov 22, 2024
1 parent e65ae91 commit f288c4b
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 90 deletions.
6 changes: 6 additions & 0 deletions rust-plugins/yaml/CHANGELOG.md
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
Expand Down
2 changes: 1 addition & 1 deletion rust-plugins/yaml/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@farmfe/plugin-yaml",
"version": "0.0.7",
"version": "0.0.8",
"private": false,
"main": "scripts/index.js",
"types": "scripts/index.d.ts",
Expand Down
203 changes: 114 additions & 89 deletions rust-plugins/yaml/src/lib.rs
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(&param.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>(&param.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(&param.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>(&param.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(&param.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,
}))
}
}

0 comments on commit f288c4b

Please sign in to comment.