#![feature(proc_macro_hygiene, decl_macro)] #[macro_use] extern crate rocket; use failure::Error; use rocket::response::content; use serde::Serialize; #[derive(Debug, Serialize)] struct Todos { todos: Vec, } #[derive(Debug, Serialize)] struct TodoItem { done: bool, item: String, } fn find_all_todos(doc: &two_trucs::parse::Doc, todos: &mut Vec) -> Result<(), Error> { use two_trucs::parse::Node; use two_trucs::render::render_document; for node in doc.iter() { if let Node::Node { tag: _, children } = node { if let Some(Node::TaskListMarker(done)) = children.first() { let mut item = std::io::Cursor::new(Vec::new()); render_document(&children.iter().cloned().skip(1).collect(), &mut item)?; todos.push(TodoItem { done: *done, item: String::from_utf8(item.into_inner())? }); } find_all_todos(children, todos)?; } } Ok(()) } fn get_todos(path: &std::path::Path) -> Result { use pulldown_cmark::{Options, Parser}; use std::io::Read; let mut str = String::new(); std::fs::File::open(path)?.read_to_string(&mut str)?; let doc = two_trucs::parse::DocBuilder::from( Parser::new_ext(&str, Options::all())).build(); let mut todos = Vec::new(); find_all_todos(&doc, &mut todos)?; Ok(Todos { todos }) } #[get("/todo")] fn todo() -> content::Json { let todos = get_todos(std::path::Path::new("example.md")).unwrap(); content::Json(serde_json::to_string(&todos).unwrap()) } #[get("/")] fn index() -> rocket::response::NamedFile { rocket::response::NamedFile::open("static/index.html").unwrap() } fn main() { rocket::ignite().mount("/", routes![index, todo]).launch(); }