@ape-egg/vibe-compiler 4.3.3 → 4.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/native/vibe-compiler-darwin-arm64 +0 -0
- package/native/vibe-compiler-linux-x64 +0 -0
- package/package.json +1 -1
- package/src/Cargo.lock +1 -1
- package/src/Cargo.toml +1 -1
- package/src/parser/html.rs +71 -17
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ape-egg/vibe-compiler",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Optional Rust compiler for Vibe \u2014 pre-renders, inlines components, and optimizes iterations. The runtime never needs it.",
|
|
6
6
|
"homepage": "https://vibe.korte.kim",
|
package/src/Cargo.lock
CHANGED
package/src/Cargo.toml
CHANGED
package/src/parser/html.rs
CHANGED
|
@@ -653,6 +653,51 @@ fn is_iter_prop_root(template: &str) -> bool {
|
|
|
653
653
|
/// literal props inject the value (bare boolean attrs → true, strings
|
|
654
654
|
/// JSON-quoted, numerics raw).
|
|
655
655
|
fn substitute_props(template: &str, props: &[(String, String)]) -> String {
|
|
656
|
+
let raw_text_re =
|
|
657
|
+
regex::Regex::new(r"(?is)(<(?:script|style)\b[^>]*>)(.*?)(</(?:script|style)\s*>)").unwrap();
|
|
658
|
+
|
|
659
|
+
let mut out = String::with_capacity(template.len());
|
|
660
|
+
let mut last = 0;
|
|
661
|
+
for caps in raw_text_re.captures_iter(template) {
|
|
662
|
+
let whole = caps.get(0).unwrap();
|
|
663
|
+
out.push_str(&substitute_props_in(&template[last..whole.start()], props, true));
|
|
664
|
+
out.push_str(&substitute_props_in(caps.get(1).unwrap().as_str(), props, true));
|
|
665
|
+
out.push_str(&substitute_props_in(caps.get(2).unwrap().as_str(), props, false));
|
|
666
|
+
out.push_str(caps.get(3).unwrap().as_str());
|
|
667
|
+
last = whole.end();
|
|
668
|
+
}
|
|
669
|
+
out.push_str(&substitute_props_in(&template[last..], props, true));
|
|
670
|
+
out
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
fn escape_attr_value(value: &str) -> String {
|
|
674
|
+
value
|
|
675
|
+
.replace('&', "&")
|
|
676
|
+
.replace('"', """)
|
|
677
|
+
.replace('\'', "'")
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
fn decode_entities(value: &str) -> String {
|
|
681
|
+
value
|
|
682
|
+
.replace(""", "\"")
|
|
683
|
+
.replace(""", "\"")
|
|
684
|
+
.replace("'", "'")
|
|
685
|
+
.replace("'", "'")
|
|
686
|
+
.replace("<", "<")
|
|
687
|
+
.replace(">", ">")
|
|
688
|
+
.replace(" ", "\u{a0}")
|
|
689
|
+
.replace("&", "&")
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
fn substitute_props_in(template: &str, props: &[(String, String)], entity_decoded: bool) -> String {
|
|
693
|
+
let escaped = |value: &str| {
|
|
694
|
+
if entity_decoded {
|
|
695
|
+
escape_attr_value(value)
|
|
696
|
+
} else {
|
|
697
|
+
value.to_string()
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
|
|
656
701
|
let binding_re = regex::Regex::new(r"@\[([^\]]+)\]").unwrap();
|
|
657
702
|
let directive_re = regex::Regex::new(r"(?s)<!--\s*(if|else if|each)\s+(.*?)\s*-->").unwrap();
|
|
658
703
|
let event_re = regex::Regex::new(r#"\bon(\w+)="([^"]*)""#).unwrap();
|
|
@@ -660,7 +705,8 @@ fn substitute_props(template: &str, props: &[(String, String)]) -> String {
|
|
|
660
705
|
|
|
661
706
|
let mut html = template.to_string();
|
|
662
707
|
|
|
663
|
-
for (prop_name,
|
|
708
|
+
for (prop_name, raw_value) in props {
|
|
709
|
+
let prop_value = decode_entities(raw_value);
|
|
664
710
|
let exact_re =
|
|
665
711
|
regex::Regex::new(&format!(r"(?i)@\[{}\]", regex::escape(prop_name))).unwrap();
|
|
666
712
|
|
|
@@ -668,23 +714,31 @@ fn substitute_props(template: &str, props: &[(String, String)]) -> String {
|
|
|
668
714
|
.strip_prefix("@[")
|
|
669
715
|
.and_then(|v| v.strip_suffix(']'));
|
|
670
716
|
|
|
671
|
-
let (exact_repl, ident_repl, each_repl, state_repl) =
|
|
672
|
-
(
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
"true".to_string()
|
|
681
|
-
} else if numeric_re.is_match(prop_value) {
|
|
682
|
-
prop_value.clone()
|
|
717
|
+
let (exact_repl, ident_repl, directive_repl, each_repl, state_repl) =
|
|
718
|
+
if let Some(path) = binding_path {
|
|
719
|
+
(
|
|
720
|
+
format!("@[{}]", path),
|
|
721
|
+
format!("({})", path),
|
|
722
|
+
format!("({})", path),
|
|
723
|
+
path.to_string(),
|
|
724
|
+
path.to_string(),
|
|
725
|
+
)
|
|
683
726
|
} else {
|
|
684
|
-
|
|
727
|
+
let literal = if prop_value.is_empty() {
|
|
728
|
+
"true".to_string()
|
|
729
|
+
} else if numeric_re.is_match(&prop_value) {
|
|
730
|
+
prop_value.clone()
|
|
731
|
+
} else {
|
|
732
|
+
serde_json::to_string(&prop_value).unwrap()
|
|
733
|
+
};
|
|
734
|
+
(
|
|
735
|
+
escaped(&prop_value),
|
|
736
|
+
escaped(&literal),
|
|
737
|
+
literal.clone(),
|
|
738
|
+
literal.clone(),
|
|
739
|
+
escaped(&literal),
|
|
740
|
+
)
|
|
685
741
|
};
|
|
686
|
-
(prop_value.clone(), literal.clone(), literal.clone(), literal)
|
|
687
|
-
};
|
|
688
742
|
|
|
689
743
|
html = exact_re
|
|
690
744
|
.replace_all(&html, regex::NoExpand(exact_repl.as_str()))
|
|
@@ -706,7 +760,7 @@ fn substitute_props(template: &str, props: &[(String, String)]) -> String {
|
|
|
706
760
|
.replace_all(&html, |c: ®ex::Captures| {
|
|
707
761
|
let kw = c.get(1).unwrap().as_str();
|
|
708
762
|
let expr = c.get(2).unwrap().as_str();
|
|
709
|
-
let repl = if kw == "each" { each_repl.as_str() } else {
|
|
763
|
+
let repl = if kw == "each" { each_repl.as_str() } else { directive_repl.as_str() };
|
|
710
764
|
let rewritten = substitute_identifier(expr, prop_name, repl);
|
|
711
765
|
if rewritten == expr {
|
|
712
766
|
c.get(0).unwrap().as_str().to_string()
|