Sign in

    sexp-html

    HTML's s-expression representation

    s-exp
    html
    Download zip
    Author
    Version
    0.2.0
    License
    Apache-2.0
    Last updated
    5 months ago
    Downloads
    137

    #S-Expression Notation for HTML

    #Example

    • keep comments

      (% I want you to know since you came in my life)

      <!-- I want you to know since you came in my life -->

    • syntactic white spaces between terms will be ignored

      (p One hundred million and two thousand years from now (span (:style font-family: "Alegreya Sans SC", sans-serif) 爱してる) )

      <p>One hundred million and two thousand years from now <span style="font-family: \"Alegreya Sans SC\", sans-serif">爱してる</span> </p>

    • only parentheses need to be escaped

      (details (:open) (summary every day every night) \(I've been waiting to share my love with you\) you give light into the darkness skies )

      <details open> <summary>every day every night</summary> (I've been waiting to share my love with you) you give light into the darkness skies </details>

    • (~) emits a literal space, and (~tag ...) emits the normal element with one space on each side

      (p (~span hello)world)

      <p> <span>hello</span> world</p>

    • (# ...) emits an explicit raw text node and preserves the text after # exactly, including leading spaces and newlines

      The first whitespace character after # is only a separator and is not part of the text payload.

      (p (span hello) (# world))

      <p><span>hello</span> world</p>

    #Specification

    see SPEC.md.

    #AST transform API

    For custom forms that should become normal HTML-shaped nodes, parse to the public AST, transform it, then render it:

    parse_sexp_html("(p (icon search))").map(transform).map(render_html)

    The public AST is normalized to HTML-shaped nodes:

    pub(all) enum SexpNode {
    Text(String)
    Comment(String)
    Element(String, Array[(String, String?)], Array[SexpNode])
    }

    Syntax forms such as (# ...), (~), and (~tag ...) are expanded during parsing into ordinary Text and Element nodes.

    For custom forms that are rendered by existing HTML-producing tools, provide a render hook:

    sexp_to_html_with("(article (markdown **Hello**))", (node) => {
    match node {
    Element("markdown", _, [Text(source)]) => Some(markdown_to_html(source))
    _ => None
    }
    })

    When the hook returns Some(html), that string is inserted as HTML directly. When it returns None, normal rendering and escaping are used.

    SexpNode

    pub(all) enum SexpNode {
    Text(String)
    Comment(String)
    Element(String, Array[(String, String?)], Array[SexpNode])
    }

    html_to_sexp

    fn html_to_sexp(source : String) -> Result[String, String]

    is_void_tag

    fn is_void_tag(tag : String) -> Bool

    parse_sexp_html

    fn parse_sexp_html(source : String) -> Result[Array[SexpNode], String]

    render_html

    fn render_html(nodes : Array[SexpNode]) -> String

    render_html_with

    fn render_html_with(nodes : Array[SexpNode], render_custom_node : (SexpNode) -> String?) -> String

    sexp_to_html

    fn sexp_to_html(source : String) -> Result[String, String]

    sexp_to_html_with

    fn sexp_to_html_with(source : String, render_custom_node : (SexpNode) -> String?) -> Result[String, String]