use super::{
parser::{HtmlElement, HtmlNode},
react, shared, vue, FrameworkCodegenTarget, FrameworkComponentIsland,
};
use smallvec::SmallVec;
type RenderedChildren = SmallVec<[String; 8]>;
pub(super) struct FrameworkCodegen<'a> {
pub target: FrameworkCodegenTarget,
pub islands: &'a [FrameworkComponentIsland],
}
impl FrameworkCodegen<'_> {
pub(super) fn render_root(&self, nodes: &[HtmlNode]) -> String {
let children = self.render_children(nodes);
match self.target {
FrameworkCodegenTarget::React => react::render_root(&children),
FrameworkCodegenTarget::Svelte => {
unreachable!("svelte component output does not use the VDOM renderer")
}
FrameworkCodegenTarget::Vue => vue::render_root(&children),
}
}
fn render_children(&self, nodes: &[HtmlNode]) -> RenderedChildren {
let mut children = RenderedChildren::new();
for node in nodes {
if let Some(child) = self.render_node(node) {
children.push(child);
}
}
children
}
fn render_node(&self, node: &HtmlNode) -> Option<String> {
match node {
HtmlNode::Text(value) if value.is_empty() => None,
HtmlNode::Text(value) => Some(shared::js_string_literal(value)),
HtmlNode::Element(element) => Some(self.render_element(element)),
}
}
fn render_element(&self, element: &HtmlElement) -> String {
if let Some(island) = shared::find_island(element, self.islands) {
return self.render_island(island);
}
let children = self.render_children(&element.children);
match self.target {
FrameworkCodegenTarget::React => react::render_element(element, &children),
FrameworkCodegenTarget::Svelte => {
unreachable!("svelte component output does not use the VDOM renderer")
}
FrameworkCodegenTarget::Vue => vue::render_element(element, &children),
}
}
fn render_island(&self, island: &FrameworkComponentIsland) -> String {
match self.target {
FrameworkCodegenTarget::React => react::render_island(island),
FrameworkCodegenTarget::Svelte => {
unreachable!("svelte component output does not use the VDOM renderer")
}
FrameworkCodegenTarget::Vue => vue::render_island(island),
}
}
}