doccy 0.3.2

Doccy is a simple brace based markup language.
Documentation
//! Doccy is a simple brace based markup language, an alternative to writing HTML for people who enjoy the power and flexibility but do not enjoy writing it.
//!
//!
//! # Syntax
//! ## Elements
//!
//! Anything between two curley-braces is considered an element.
//!
//!
//! ### Regular Elements
//!
//! Writing an element is easy:
//!
//! ```doccy
//! {h1: Top-level heading}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <h1>Top-level heading</h1>
//! ```
//!
//!
//! ### Self closing Elements
//!
//! Some elements do not support children, and are self closing in which case the colon can be skipped entirely. For example line breaks (`<br>`) can be written as:
//!
//! ```doccy
//! {br}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <br>
//! ```
//!
//! If you use this syntax for elements that do not support being self closing in HTML, then a closing tag will be rendered:
//!
//! ```doccy
//! {div}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <div></div>
//! ```
//!
//!
//! ### Preformatted Elements
//!
//! Sometimes it is necessary to ignore Doccy syntax, you can do this with a Preformatted Element:
//!
//! ```doccy
//! {pre:#
//! You can use all of the {brackets} in here and they {em: won't be parsed!}
//! #}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <pre>You can use all of the {brackets} in here and they {em: won't be parsed!}</pre>
//! ```
//!
//! This isn't just limited to the HTML `pre` element either, you can use it on any element.
//!
//!
//! ## Attributes
//!
//! Anything between the name of an element and colon is expected to be an attribute.
//!
//!
//! ### Named Attributes
//!
//! A named attribute with a value looks like:
//!
//! ```doccy
//! {h1 @class main header: Header}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <h1 class="main header">Header</h1>
//! ```
//!
//! Without a value:
//!
//! ```doccy
//! {input @required}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <input required>
//! ```
//!
//! Values containing special characters must be escaped:
//!
//! ```doccy
//! {h1 @test Bad characters\: \@\#\%\.\{\}: ...}
//! ```
//!
//! Renders as:
//! ```html
//! <h1 test="Bad characters: @#%.{}">...</h1>
//! ```
//!
//! Unless they are part of a URL:
//!
//!
//! ```doccy
//! {a @href https://www.example.com: Example}
//! ```
//!
//! Renders as:
//! ```html
//! <a href="https://www.example.com">Example</h1>
//! ```
//!
//!
//! ### Data Attributes
//!
//! A shorthand for `data-` attributes:
//!
//! ```doccy
//! {pre %lang html: ...}
//! {pre %html: ...}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <pre data-lang="html">...</pre>
//! <pre data-html>...</pre>
//! ```
//!
//! As with named attributes, special characters must be escaped.
//!
//!
//! ### Class Attributes
//!
//! A shorthand for `class="..."` attributes:
//!
//! ```doccy
//! {h1.main.header: Header}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <h1 class="main header">Header</h1>
//! ```
//!
//!
//! ### Id Attributes
//!
//! A shorthand for `id="..."` attributes:
//!
//! ```doccy
//! {h1#main: Header}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <h1 id="main">Header</h1>
//! ```
//!
//!
//! ## Paragraphs
//!
//! Any text contained within specific contexts will be treated as one or more paragraphs if separated by two or more line breaks and it contains only inline elements.
//!
//!
//! ### In the document body
//!
//! ```doccy
//! This is a paragraph.
//!
//! {h1: This is a header.}
//!
//! And this is another.
//! ```
//!
//! Renders as:
//!
//! ```html
//! <p>This is a paragraph.</p>
//! <h1>This is a header.</h1>
//! <p>And this is another.</p>
//! ```
//!
//!
//! #### In content elements
//!
//! The following elements also automatically wrap paragraphs: `article`, `aside`, `blockquote`, `div`, `fieldset`, `footer`, `form`, `header`, `hgroup`, `main` and `section`.
//!
//! ```doccy
//! {blockquote: This is a paragraph.
//!
//! And this is another.}
//! ```
//!
//! Renders as:
//!
//! ```html
//! <blockquote>
//!     <p>This is a paragraph.</p>
//!     <p>And this is another.</p>
//! </blockquote>
//! ```
//!
//!
//! # Examples
//! ## Parsing and rendering documents:
//!
//! ```
//! use doccy::doccy_to_html;
//!
//! match doccy_to_html("your document {em: here}") {
//!     // <p>your document <em>here</em></p>
//!     Ok(html) => println!("{}", html),
//!     Err(error) => {}
//! };
//! ```
//!
//!
//! ## Using grammar and Renderer directly:
//!
//! ```
//! use doccy::grammar;
//! use doccy::render::Renderer;
//!
//! let mut renderer = Renderer::new();
//!
//! if let Ok(ast) = grammar::attributes("@href https\\://example\\.com") {
//!     renderer.attributes(&ast);
//! }
//!
//! println!("{}", renderer.output); // href="https://example.com"
//! ```

#[macro_use]
extern crate lazy_static;

pub mod ast;
pub mod grammar;
pub mod render;

use ast::Data;
use grammar::{document, ParseError};
use render::Renderer;

pub fn doccy_to_html(input: &str) -> Result<String, ParseError> {
    match document(input) {
        Ok(data) => {
            if let Data::RootElement(Some(children)) = data {
                let renderer = Renderer::new();

                Ok(renderer.root(children))
            } else {
                Ok(String::new())
            }
        }
        Err(error) => Err(error),
    }
}