Sign in

    sexp-html

    HTML's s-expression representation

    s-exp
    html
    Download zip
    Author
    Version
    0.2.2
    License
    Apache-2.0
    Last updated
    4 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)
    RawHtml(String)
    Element(String, Array[(String, String?)], Array[SexpNode])
    }

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

    Use RawHtml for trusted HTML that should be inserted directly without escaping:

    render_html([
    SexpNode::Element("p", [], [
    SexpNode::Text("<escaped> "),
    SexpNode::RawHtml("<em>trusted</em>"),
    ]),
    ])

    sexp-html also provides helpers for common HTML rendering operations:

    let attrs : Array[(String, String?)] = []
    upsert_attr(attrs, "lang", Some("en"))
    append_class(attrs, "page")

    render_open_tag("html", attrs)
    render_html_document(attrs, head, body, Some("html"))

    Cursor

    pub struct Cursor {
    chars : Array[Char]
    index : Int
    }

    SexpNode

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

    append_class

    fn append_class(attrs : Array[(String, String?)], class_name : String) -> Unit

    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], separator? : String) -> String

    render_html_document

    fn render_html_document(attrs : Array[(String, String?)], head : Array[SexpNode], body : Array[SexpNode], doctype : String?) -> String

    render_open_tag

    fn render_open_tag(tag : String, attrs : Array[(String, String?)]) -> String

    sexp_to_html

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

    upsert_attr

    fn upsert_attr(attrs : Array[(String, String?)], name : String, value : String?) -> Unit