Skip to content

Instantly share code, notes, and snippets.

@bodiam
Created April 19, 2016 13:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bodiam/7ea203cd1b928377f8afaaf9ac060d69 to your computer and use it in GitHub Desktop.
Save bodiam/7ea203cd1b928377f8afaaf9ac060d69 to your computer and use it in GitHub Desktop.
AsciidoctorJ has a dependency on JRuby, which is quite a heavy library to download and load. This one is based on Groovy, and could easily be ported to Java, and while limited, does provide quite some functionality.
/**
* A very basic regex based parser for Asciidoc.
*
* Based on Slimdown (Markdown) parsers:
* - https://gist.github.com/jbroadway/2836900
* - https://gist.github.com/renehamburger/12f14a9bd9297394e5bd
* - https://gist.github.com/paulcuth/8967731
*
* @author Erik Pragt
*/
class AsciiLite {
private static def para = {
String line = it[1]
String trimmed = line.trim()
if (trimmed =~ /^<\/?(ul|ol|li|h|p|bl)|(<!--)/) {
return "\n${line}\n"
} else {
return "\n<p>$trimmed</p>\n"
}
}
private static def blockquote = {
return "\n<blockquote>${it[2].trim()}</blockquote>"
}
private static def ul_list = {
return "\n<ul>\n\t<li>${it[1].trim()}</li>\n</ul>"
}
private static def ol_list = {
return "\n<ol>\n\t<li>${it[1].trim()}</li>\n</ol>"
}
private static def header = {
def s = it[1].size()
return "<h$s>${it[2].trim()}</h$s>"
}
private static def rules = [
/(=+)(.*)/ : header, // header
/(^|\s)\/\/\s?(.*)/ : '<!-- $2 -->', // comment
/image::(.*)\[\]/ : '<img src="$1">', // image
/([^\n)]+)\[([^\[]+)\]/ : '<a href="$1">$2</a>', // links
/(\*)(.*?)\1/ : '<strong>$2</strong>', // bold
/(_)(.*?)\1/ : '<em>$2</em>', // emphasis
/(\[line-through\])(.*)/ : '<del>$2</del>', // del
// '/\:\"(.*?)\"\:/' => '<q>\1</q>', // quote /??
/(\+)(.*?)\1/ : '<code>$2</code>', // inline code
/\n\*(.*)/ : ul_list, // ul lists
/\n\.(.*)/ : ol_list, // ol lists
/\n(&gt;|\>)(.*)/ : blockquote, // blockquotes
/'''/ : '<hr />', // horizontal rule
/\n([^\n]+)\n/ : para, // add paragraphs
/<\/ul>\s?<ul>/ : '', // fix extra ul
/<\/ol>\s?<ol>/ : '', // fix extra ol
/<\/blockquote>\n<blockquote>/: "\n", // fix extra blockquote
/<p><\/p>/ : '' // fix extra p
]
static String render(String input) {
def result = "\n" + input + "\n"
rules.each { k, v ->
result = result.replaceAll(k, v)
}
result.trim()
}
}
@bodiam
Copy link
Author

bodiam commented Apr 19, 2016

class AsciiLiteTest
{

    @Ignore("This is still an issue")
    public void split_paragraph() {
        assert AsciiLite.render("\nhello world\nhow are you?\n") == '\n<p>hello world how are you?</p>\n'
    }

    @Ignore("Not sure how quotes work in Asciidoctor")
    public void quote() {
//        assert AsciiLite.render("http://example.com/[example link]") == '<a href="http://example.com/">example link</a>'
    }

    @Test
    void testHeaders() {
        assert AsciiLite.render("= Header") == "<h1>Header</h1>"
        assert AsciiLite.render("== Header") == "<h2>Header</h2>"
        assert AsciiLite.render("=== Header") == "<h3>Header</h3>"
        assert AsciiLite.render("==== Header") == "<h4>Header</h4>"
        assert AsciiLite.render("===== Header") == "<h5>Header</h5>"
        assert AsciiLite.render("====== Header") == "<h6>Header</h6>"
    }

    @Test
    public void bold() {
        assert AsciiLite.render("*hello*") == "<p><strong>hello</strong></p>"
    }

    @Test
    public void italic() {
        assert AsciiLite.render("_hello_") == "<p><em>hello</em></p>"
    }

    @Test
    public void mono() {
        assert AsciiLite.render("+hello+") == "<p><code>hello</code></p>"
    }

    @Test
    public void del() {
        assert AsciiLite.render("[line-through]hello") == "<p><del>hello</del></p>"
    }

    @Test
    public void ruler() {
        assert AsciiLite.render("'''") == "<hr />"
    }

    @Test
    public void link() {
        assert AsciiLite.render("http://example.com/[example link]") == '<p><a href="http://example.com/">example link</a></p>'
    }

    @Test
    public void comment() {
        assert AsciiLite.render("// A single-line comment.") == '<!-- A single-line comment. -->'
    }

    @Test
    public void img() {
        assert AsciiLite.render("image::sunset.jpg[]") == '<p><img src="sunset.jpg"></p>'
    }

    @Ignore
    public void complexlink() {
        assert AsciiLite.render("[example link](http://example.com/)") == """This is an [example link](http://example.com/)."""
    }

    @Test
    public void ul() {
        def input = """
                    * item1""".stripIndent()

        def expected = """<ul>
                         |\t<li>item1</li>
                         |</ul>""".stripMargin()

        assert AsciiLite.render(input) == expected
    }

    @Test
    public void multi_ul() {
        def input = """
                    * item1
                    * item2""".stripIndent()

        def expected = """<ul>
                         |\t<li>item1</li>
                         |
                         |\t<li>item2</li>
                         |</ul>""".stripMargin()

        assert AsciiLite.render(input) == expected
    }

    @Test
    public void render() {
        println AsciiLite.render(
                """= hello world
                  |
                  |welcome to *my* first test
                  |
                  |== credits
                  |
                  |in no order:
                  |
                  |* erik
                  |* pietje"
                  """.stripMargin())
//        println AsciiLite.render("= hello world\n\nwelcome to *my* first test\n\n== credits\n\nin no order:\n\n* erik\n* pietje")
    }

    @Test
    public void li() {
        def input = """
                    . item1""".stripIndent()

        def expected = """<ol>
                         |\t<li>item1</li>
                         |</ol>""".stripMargin()

        assert AsciiLite.render(input) == expected
    }

    @Test
    public void multi_li() {
        def input = """
                    . item1
                    . item2""".stripIndent()

        def expected = """<ol>
                         |\t<li>item1</li>
                         |
                         |\t<li>item2</li>
                         |</ol>""".stripMargin()

        assert AsciiLite.render(input) == expected
    }

    @Test
    public void blockquote() {
        assert AsciiLite.render("\n> quote") == '<blockquote>quote</blockquote>'
    }

    @Test
    public void multi_blockquote() {
        assert AsciiLite.render("\n> quote1\n> quote2") == '<blockquote>quote1\nquote2</blockquote>'
    }

    @Test
    public void paragraph() {
        assert AsciiLite.render("\nhello world\n") == '<p>hello world</p>'
    }

    @Test
    public void multi_paragraph() {
        assert AsciiLite.render("\nhello world\n\nhow are you?") == '<p>hello world</p>\n\n<p>how are you?</p>'
    }
}

@SuperMMX
Copy link

For someone who is interested, I am working on a Groovy implementation of AsciiDoc called "AsciiDog": https://github.com/SuperMMX/asciidog, now it has a very basic working version that can output to HTML5 and epub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment