use crate::ast::*;
use crate::transform::TransformContext;
use vize_carton::String;
use vize_carton::ToCompactString;
pub fn has_v_once(el: &ElementNode<'_>) -> bool {
el.props
.iter()
.any(|prop| matches!(prop, PropNode::Directive(dir) if dir.name == "once"))
}
pub fn remove_v_once(el: &mut ElementNode<'_>) {
let mut i = 0;
while i < el.props.len() {
if let PropNode::Directive(dir) = &el.props[i] {
if dir.name == "once" {
el.props.remove(i);
return;
}
}
i += 1;
}
}
pub fn transform_v_once<'a>(ctx: &mut TransformContext<'a>, _el: &ElementNode<'a>) -> bool {
ctx.in_v_once = true;
ctx.helper(RuntimeHelper::SetBlockTracking);
true
}
pub fn generate_v_once_wrapper(index: usize) -> String {
let index_str = index.to_compact_string();
let mut out = String::with_capacity(32 + index_str.len());
out.push_str("_cache[");
out.push_str(&index_str);
out.push_str("] || (_setBlockTracking(-1), _cache[");
out.push_str(&index_str);
out.push_str("] = ");
out
}
#[cfg(test)]
mod tests {
use super::{has_v_once, TemplateChildNode};
use crate::parser::parse;
use bumpalo::Bump;
#[test]
fn test_has_v_once() {
let allocator = Bump::new();
let (root, _) = parse(&allocator, r#"<div v-once>static</div>"#);
if let TemplateChildNode::Element(el) = &root.children[0] {
assert!(has_v_once(el));
}
}
#[test]
fn test_no_v_once() {
let allocator = Bump::new();
let (root, _) = parse(&allocator, r#"<div>dynamic</div>"#);
if let TemplateChildNode::Element(el) = &root.children[0] {
assert!(!has_v_once(el));
}
}
}