Rendering spans
This commit is contained in:
parent
13934e8699
commit
2459d7b418
15
src/bin.rs
15
src/bin.rs
@ -30,16 +30,27 @@ fn main() {
|
||||
.iter()
|
||||
.map(|(p, contents)| template_from_file(p, contents))
|
||||
.collect();
|
||||
let mut dust_context = DustRenderer::new();
|
||||
let mut dust_renderer = DustRenderer::new();
|
||||
compiled_templates.iter().for_each(|template| {
|
||||
dust_context.load_source(template);
|
||||
dust_renderer.load_source(template);
|
||||
});
|
||||
let main_template_name = &compiled_templates
|
||||
.first()
|
||||
.expect("There should be more than 1 template")
|
||||
.name;
|
||||
println!(
|
||||
"{}",
|
||||
dust_renderer
|
||||
.render(main_template_name, context)
|
||||
.expect("Failed to render")
|
||||
);
|
||||
}
|
||||
|
||||
fn template_from_file<'a>(file_path: &str, file_contents: &'a str) -> CompiledTemplate<'a> {
|
||||
let path: &Path = Path::new(file_path);
|
||||
let name = path.file_stem().unwrap();
|
||||
compile_template(file_contents, name.to_string_lossy().to_string())
|
||||
.expect("Failed to compile template")
|
||||
}
|
||||
|
||||
fn read_context_from_stdin() -> serde_json::map::Map<String, serde_json::Value> {
|
||||
|
@ -8,3 +8,4 @@ pub use node_invoker::NodeError;
|
||||
pub use node_invoker::Result;
|
||||
pub use parser::template;
|
||||
pub use parser::Template;
|
||||
pub use parser::TemplateElement;
|
||||
|
@ -24,7 +24,7 @@ use nom::sequence::tuple;
|
||||
use nom::IResult;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum DustTag<'a> {
|
||||
pub enum DustTag<'a> {
|
||||
DTSpecial(Special),
|
||||
DTComment(Comment<'a>),
|
||||
DTReference(Reference<'a>),
|
||||
@ -79,8 +79,8 @@ enum Filter {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct Span<'a> {
|
||||
contents: &'a str,
|
||||
pub struct Span<'a> {
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@ -123,17 +123,17 @@ struct KVPair<'a> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct Body<'a> {
|
||||
elements: Vec<TemplateElement<'a>>,
|
||||
pub struct Body<'a> {
|
||||
pub elements: Vec<TemplateElement<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Template<'a> {
|
||||
contents: Body<'a>,
|
||||
pub contents: Body<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum TemplateElement<'a> {
|
||||
pub enum TemplateElement<'a> {
|
||||
TESpan(Span<'a>),
|
||||
TETag(DustTag<'a>),
|
||||
}
|
||||
|
48
src/renderer/errors.rs
Normal file
48
src/renderer/errors.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RenderError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CompileError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for RenderError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error rendering: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for RenderError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error rendering: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for RenderError {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error rendering: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CompileError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error rendering: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for CompileError {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
//! This module contains a renderer for a rust implementation of LinkedIn Dust
|
||||
|
||||
mod errors;
|
||||
mod renderer;
|
||||
|
||||
pub use renderer::compile_template;
|
||||
|
@ -1,41 +1,73 @@
|
||||
use crate::parser::template;
|
||||
use crate::parser::Template;
|
||||
use nom::IResult;
|
||||
use std::collections::BTreeMap;
|
||||
use crate::parser::TemplateElement;
|
||||
use crate::renderer::errors::CompileError;
|
||||
use crate::renderer::errors::RenderError;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Index;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CompiledTemplate<'a> {
|
||||
template: Template<'a>,
|
||||
name: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DustRenderer<'a> {
|
||||
templates: BTreeMap<&'a String, &'a Template<'a>>,
|
||||
templates: HashMap<String, &'a Template<'a>>,
|
||||
}
|
||||
|
||||
pub fn compile_template<'a>(source: &'a str, name: String) -> CompiledTemplate<'a> {
|
||||
// TODO: Make this function return a result with a custom error type. Break the nom IResult chain
|
||||
pub fn compile_template<'a>(
|
||||
source: &'a str,
|
||||
name: String,
|
||||
) -> Result<CompiledTemplate<'a>, CompileError> {
|
||||
// TODO: Make this all consuming
|
||||
// TODO: This could use better error management
|
||||
let (_remaining, parsed_template) = template(source).expect("Failed to compile template");
|
||||
CompiledTemplate {
|
||||
Ok(CompiledTemplate {
|
||||
template: parsed_template,
|
||||
name: name,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a> DustRenderer<'a> {
|
||||
pub fn new() -> DustRenderer<'a> {
|
||||
DustRenderer {
|
||||
templates: BTreeMap::new(),
|
||||
templates: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_source(&mut self, template: &'a CompiledTemplate) {
|
||||
self.templates.insert(&template.name, &template.template);
|
||||
self.templates
|
||||
.insert(template.name.clone(), &template.template);
|
||||
}
|
||||
|
||||
// pub fn render(&self, context) {
|
||||
pub fn render<C>(&self, name: &str, context: C) -> Result<String, RenderError>
|
||||
where
|
||||
C: Index<&'a str>,
|
||||
{
|
||||
let main_template = match self.templates.get(name) {
|
||||
Some(tmpl) => tmpl,
|
||||
None => {
|
||||
return Err(RenderError {
|
||||
message: format!("No template named {} in context", name),
|
||||
});
|
||||
}
|
||||
};
|
||||
self.render_template(main_template, context)
|
||||
}
|
||||
|
||||
// }
|
||||
fn render_template<C>(&self, template: &Template, context: C) -> Result<String, RenderError>
|
||||
where
|
||||
C: Index<&'a str>,
|
||||
{
|
||||
let mut output = String::new();
|
||||
for elem in &template.contents.elements {
|
||||
match elem {
|
||||
TemplateElement::TESpan(span) => output.push_str(span.contents),
|
||||
TemplateElement::TETag(dt) => (),
|
||||
}
|
||||
}
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user