From 0e8876eede07b63898e33a022ad298275c84fde0 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Fri, 22 May 2026 13:07:56 +0200 Subject: [PATCH] feat: Option to hide original element --- Cargo.lock | 21 ++++++++++++ Cargo.toml | 2 ++ src/compiler/compiler.rs | 3 ++ src/compiler/config.rs | 50 +++++++++++++++++++++++++++ src/compiler/mod.rs | 1 + src/compiler/models.rs | 1 + src/compiler/models_impl.rs | 67 +++++++++++++++++++++++++++---------- 7 files changed, 128 insertions(+), 17 deletions(-) create mode 100644 src/compiler/config.rs diff --git a/Cargo.lock b/Cargo.lock index 294e346..529144d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1577,6 +1577,19 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "simd-abstraction" version = "0.7.1" @@ -1676,7 +1689,9 @@ dependencies = [ "oxc_parser", "oxc_span", "rand", + "serde", "serde_json", + "serde_yaml", ] [[package]] @@ -1755,6 +1770,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "utf8parse" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index d9eb07e..e327792 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ version = "0.1.0" edition = "2024" [dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.9" serde_json = "1.0" clap = { version = "4.0", features = ["derive"] } indoc = "2" diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index 99c913e..c83ab0f 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -117,10 +117,13 @@ fn construct_template(template_path: &str) -> Template { ); }); + let config_path = format!("{}/config.yaml", template_path); + Template::TemplateInjector { template: template_content, replace_selector: replace_selector.trim().to_string(), scraper, + config_path: Some(config_path), script: post_script, style, } diff --git a/src/compiler/config.rs b/src/compiler/config.rs new file mode 100644 index 0000000..6aed803 --- /dev/null +++ b/src/compiler/config.rs @@ -0,0 +1,50 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize, PartialEq)] +pub enum ReplaceType { + #[serde(rename = "hide")] + Hide, + #[serde(rename = "replace")] + Replace, +} + +impl Default for ReplaceType { + fn default() -> Self { + ReplaceType::Replace + } +} + +#[derive(Debug, Deserialize, Default)] +pub struct TemplateReplacer { + #[serde(default)] + pub replace_type: ReplaceType, +} + +#[derive(Debug, Deserialize, Default)] +pub struct Scraper { + #[serde(default)] + pub rerender_key: String, +} + +#[derive(Debug, Deserialize, Default)] +pub struct Config { + #[serde(default)] + pub template_replacer: TemplateReplacer, + #[serde(default)] + pub scraper: Scraper, +} + +impl Config { + pub fn load(path: &Option) -> Self { + match path { + Some(path_str) => match std::fs::File::open(path_str) { + Ok(file) => { + let reader = std::io::BufReader::new(file); + serde_yaml::from_reader(reader).unwrap_or_default() + } + Err(_) => Config::default(), + }, + None => Config::default(), + } + } +} diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 54e88ec..688cb55 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -1,2 +1,3 @@ pub mod compiler; pub mod models; +pub mod config; diff --git a/src/compiler/models.rs b/src/compiler/models.rs index 10ac33f..d1af7e6 100644 --- a/src/compiler/models.rs +++ b/src/compiler/models.rs @@ -31,6 +31,7 @@ pub enum Template { scraper: Option, style: Option, script: Option, + config_path: Option, }, } diff --git a/src/compiler/models_impl.rs b/src/compiler/models_impl.rs index f01f932..183a1f4 100644 --- a/src/compiler/models_impl.rs +++ b/src/compiler/models_impl.rs @@ -1,6 +1,7 @@ use indoc::indoc; use serde_json; +use crate::compiler::config::{Config, ReplaceType}; use crate::css::{minify_css, scope_css}; use crate::compiler::models::{PageRoute, Project, Template}; @@ -142,6 +143,7 @@ impl Template { scraper, script, style, + config_path, } => { let scope_class = format!("template-style-{}", rand::random::()); let script = if let Some(script) = script { @@ -154,6 +156,8 @@ impl Template { String::new() }; + let config = Config::load(config_path); + let style_script = if let Some(style) = style { if style.trim().is_empty() { String::new() @@ -175,29 +179,58 @@ impl Template { String::new() }; - let script_template = indoc! { r#" - (function() { - {style_script} + let script_template = + if config.template_replacer.replace_type == ReplaceType::Replace { + indoc! { r#" + (function() { + {style_script} - const parsedData = eval({scraper} || "(() => ({}))"); - const template = Handlebars.compile({template}); - const rendered = template(parsedData); - const targetElement = document.querySelector({replace_selector}); + const parsedData = eval({scraper} || "(() => ({}))"); + const template = Handlebars.compile({template}); + const rendered = template(parsedData); + const targetElement = document.querySelector({replace_selector}); - const temp = document.createElement('template'); - temp.innerHTML = rendered; + const temp = document.createElement('template'); + temp.innerHTML = rendered; - const newElement = temp.content.firstElementChild; + const newElement = temp.content.firstElementChild; - targetElement.replaceWith(newElement); + targetElement.replaceWith(newElement); - newElement.classList.add({scope_class}); + newElement.classList.add({scope_class}); - (function() { - {script} - })(); - })(); - "# }; + (function() { + {script} + })(); + })(); + "# + } + } else { + indoc! { r#" + (function() { + {style_script} + + const parsedData = eval({scraper} || "(() => ({}))"); + const template = Handlebars.compile({template}); + const rendered = template(parsedData); + const targetElement = document.querySelector({replace_selector}); + + targetElement.style.display = 'none'; + + const temp = document.createElement('template'); + temp.innerHTML = rendered; + const newElement = temp.content.firstElementChild; + + targetElement.after(newElement); + + newElement.classList.add({scope_class}); + + (function() { + {script} + })(); + })(); + "# } + }; script_template .replace("{style_script}", &style_script.trim())