Skip to content

Commit c8d175a

Browse files
authored
Merge pull request #271 from egohygiene/copilot/implement-command-based-executor
feat: integrate command-based executor into build pipeline
2 parents 9b54209 + 9cca7ca commit c8d175a

3 files changed

Lines changed: 62 additions & 4 deletions

File tree

src/commands/build.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::optimization::OptimizationMode;
1616
use crate::pipeline::{Pipeline, StrategyStep};
1717
use crate::strategies::select_strategy;
1818
use crate::template::{init_tera, validate_templates};
19+
use crate::transforms::{load_transforms_from_yaml, FailureMode, TransformRegistry};
1920

2021
/// Run the full build pipeline.
2122
///
@@ -120,6 +121,20 @@ fn run_impl(config_path: &str, dry_run: bool, resilient: bool, optimization: Opt
120121
// gracefully. Only write back to disk in non-dry-run mode.
121122
let mut transform_cache = load_cache(&cache_path);
122123

124+
// Load command-based transforms from the YAML file specified in config, if any.
125+
// These are applied after the standard built-in pipeline (emoji, variables, syntax).
126+
let command_registry: Option<TransformRegistry> = if let Some(ref path) = config.transforms {
127+
info!(path = %path, "Loading command-based transforms");
128+
let mode = if resilient { FailureMode::ContinueOnError } else { FailureMode::FailFast };
129+
Some(
130+
load_transforms_from_yaml(path)
131+
.with_context(|| format!("Failed to load command-based transforms from '{}'", path))?
132+
.with_failure_mode(mode),
133+
)
134+
} else {
135+
None
136+
};
137+
123138
pb.set_message(if dry_run { "[DRY RUN] Applying transforms" } else { "Applying transforms" });
124139
let mut format_transformed: HashMap<String, String> = HashMap::new();
125140
for output in &config.outputs {
@@ -139,9 +154,18 @@ fn run_impl(config_path: &str, dry_run: bool, resilient: bool, optimization: Opt
139154
} else {
140155
Pipeline::with_standard_transforms(&config.variables, format)
141156
};
142-
pipeline
157+
let standard_output = pipeline
143158
.run_transforms(normalized_content.as_ref().to_owned())
144-
.with_context(|| format!("Transform pipeline failed for format: {format_str}; aborting build"))?
159+
.with_context(|| format!("Transform pipeline failed for format: {format_str}; aborting build"))?;
160+
// Apply command-based transforms (e.g. ImageMagick, Pandoc) if configured.
161+
if let Some(ref cmd_registry) = command_registry {
162+
debug!(format = %format_str, "Applying command-based transforms");
163+
cmd_registry
164+
.apply_all(standard_output)
165+
.with_context(|| format!("Command transform pipeline failed for format: {format_str}"))?
166+
} else {
167+
standard_output
168+
}
145169
};
146170

147171
if !dry_run {

src/config.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ pub struct Config {
8383
/// Defaults to [`OptimizationMode::Balanced`] when omitted.
8484
#[serde(default)]
8585
pub optimization: OptimizationMode,
86+
/// Optional path to a YAML file defining additional command-based transforms.
87+
///
88+
/// When set, the named transforms are loaded and applied after the standard
89+
/// built-in pipeline (emoji replacement, variable substitution, syntax
90+
/// highlighting). The file must conform to the schema expected by
91+
/// [`crate::transforms::load_transforms_from_yaml`].
92+
#[serde(default)]
93+
pub transforms: Option<String>,
8694
}
8795

8896
impl Config {
@@ -603,4 +611,31 @@ output_dir: "dist"
603611
"error should mention unsupported output: {msg}"
604612
);
605613
}
614+
615+
#[test]
616+
fn test_load_config_with_transforms_path() {
617+
let yaml = r#"
618+
outputs:
619+
- type: html
620+
input: "input.md"
621+
output_dir: "dist"
622+
transforms: "transforms.yaml"
623+
"#;
624+
let f = write_temp_yaml(yaml);
625+
let config = load_config(f.path().to_str().unwrap()).expect("should parse with transforms");
626+
assert_eq!(config.transforms.as_deref(), Some("transforms.yaml"));
627+
}
628+
629+
#[test]
630+
fn test_load_config_without_transforms_defaults_to_none() {
631+
let yaml = r#"
632+
outputs:
633+
- type: html
634+
input: "input.md"
635+
output_dir: "dist"
636+
"#;
637+
let f = write_temp_yaml(yaml);
638+
let config = load_config(f.path().to_str().unwrap()).expect("should parse without transforms");
639+
assert!(config.transforms.is_none());
640+
}
606641
}

src/transforms/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ mod transform;
66
mod variable;
77
pub mod yaml_loader;
88

9-
pub use command::CommandTransform;
109
pub use emoji::EmojiTransform;
1110
pub use registry::{register_transforms, FailureMode, TransformRegistry};
1211
pub use syntax_highlight::SyntaxHighlightTransform;
1312
pub use transform::Transform;
1413
pub use variable::VariableSubstitutionTransform;
15-
pub use yaml_loader::{load_transforms_from_yaml, parse_transforms_from_str, YamlTransformConfig, YamlTransformDef};
14+
pub use yaml_loader::load_transforms_from_yaml;

0 commit comments

Comments
 (0)