use vize_carton::{String, ToCompactString};
use super::string_tracking::{
compact_render_body, count_braces_with_state, count_parens_with_state, StringTrackState,
};
fn is_vapor_template_declaration(line: &str) -> bool {
line.starts_with("const t") && line.contains("_template(")
}
pub(crate) fn extract_template_parts_full(template_code: &str) -> (String, String, String) {
let mut imports = String::default();
let mut hoisted = String::default();
let mut render_fn = String::default();
let mut in_render = false;
let mut brace_depth = 0;
let mut brace_state = StringTrackState::default();
for line in template_code.lines() {
let trimmed = line.trim();
if trimmed.starts_with("import ") {
imports.push_str(line);
imports.push('\n');
} else if trimmed.starts_with("export function render(")
|| trimmed.starts_with("function render(")
{
in_render = true;
brace_depth = 0;
brace_state = StringTrackState::default();
brace_depth += count_braces_with_state(line, &mut brace_state);
render_fn.push_str(line);
render_fn.push('\n');
} else if trimmed.starts_with("const _hoisted_")
|| is_vapor_template_declaration(trimmed)
|| (!trimmed.is_empty() && !in_render)
{
hoisted.push_str(line);
hoisted.push('\n');
} else if in_render {
brace_depth += count_braces_with_state(line, &mut brace_state);
render_fn.push_str(line);
render_fn.push('\n');
if brace_depth == 0 {
in_render = false;
}
}
}
(imports, hoisted, render_fn)
}
#[allow(dead_code)]
pub(crate) fn extract_template_parts(template_code: &str) -> (String, String, String, String) {
let mut imports = String::default();
let mut hoisted = String::default();
let mut preamble = String::default(); let mut render_body = String::default();
let mut in_render = false;
let mut in_block_render = false;
let mut saw_block_render = false;
let mut in_return = false;
let mut brace_depth = 0;
let mut brace_state = StringTrackState::default();
let mut paren_state = StringTrackState::default();
let mut return_paren_depth = 0;
let lines: Vec<&str> = template_code.lines().collect();
for (i, line) in lines.iter().enumerate() {
let trimmed = line.trim();
if trimmed.starts_with("import ") {
imports.push_str(line);
imports.push('\n');
} else if trimmed.starts_with("const _hoisted_") || is_vapor_template_declaration(trimmed) {
hoisted.push_str(line);
hoisted.push('\n');
} else if trimmed.starts_with("export function render(")
|| trimmed.starts_with("function render(")
{
in_render = true;
in_block_render = trimmed.starts_with("function render(") && trimmed.contains("$props");
saw_block_render = saw_block_render || in_block_render;
brace_depth = 0;
brace_state = StringTrackState::default();
paren_state = StringTrackState::default();
brace_depth += count_braces_with_state(line, &mut brace_state);
} else if in_render {
let brace_delta = count_braces_with_state(line, &mut brace_state);
let next_brace_depth = brace_depth + brace_delta;
if in_block_render {
if !(next_brace_depth == 0 && trimmed == "}") {
if !render_body.is_empty() {
render_body.push('\n');
}
render_body.push_str(line);
}
brace_depth = next_brace_depth;
if brace_depth == 0 {
in_render = false;
in_block_render = false;
}
continue;
}
brace_depth = next_brace_depth;
if in_return {
render_body.push('\n');
render_body.push_str(line);
return_paren_depth += count_parens_with_state(line, &mut paren_state);
if return_paren_depth <= 0 {
let next_continues_ternary = lines
.iter()
.skip(i + 1)
.map(|l| l.trim())
.find(|l| !l.is_empty())
.map(|l| l.starts_with('?') || l.starts_with(':'))
.unwrap_or(false);
if !next_continues_ternary {
in_return = false;
let trimmed_body = render_body.trim_end();
if let Some(stripped) = trimmed_body.strip_suffix(';') {
render_body = stripped.to_compact_string();
}
}
}
} else if let Some(stripped) = trimmed.strip_prefix("return ") {
render_body = stripped.to_compact_string();
paren_state = StringTrackState::default();
return_paren_depth = count_parens_with_state(stripped, &mut paren_state);
if return_paren_depth > 0 {
in_return = true;
} else {
let next_continues_ternary = lines
.iter()
.skip(i + 1)
.map(|l| l.trim())
.find(|l| !l.is_empty())
.map(|l| l.starts_with('?') || l.starts_with(':'))
.unwrap_or(false);
if next_continues_ternary {
in_return = true;
} else {
if render_body.ends_with(';') {
render_body.pop();
}
}
}
} else if trimmed.starts_with("const _component_")
|| trimmed.starts_with("const _directive_")
{
preamble.push_str(trimmed);
preamble.push('\n');
}
if brace_depth == 0 {
in_render = false;
}
}
}
let compacted = if saw_block_render {
render_body
} else {
compact_render_body(&render_body)
};
(imports, hoisted, preamble, compacted)
}