Installing and Using Asciidoctor.js

Asciidoctor.js is a JavaScript port of Asciidoctor. With asciidoctor.js, the AsciiDoc syntax can be used in the browser!

Introduction

The asciidoctor.js project is a direct port of Asciidoctor from Ruby to JavaScript using the Opal Ruby-to-JavaScript cross compiler. It consists of a Rake build script that executes the Opal compiler on the Asciidoctor source code to produce the asciidoctor.js script.

Opal parses the Ruby code and any required libraries, then rewrites the code into JavaScript under the Opal namespace. The resulting JavaScript can be executed within any JavaScript runtime environment (such as a browser).

To interact with the generated code, you either invoke the JavaScript APIs directly, or you can invoke native JavaScript objects from within the Ruby code prior to compilation.

Setup

Start by cloning the source from GitHub.

$ git clone --recurse-submodules git://github.com/asciidoctor/asciidoctor.js

Next, switch to the asciidoctor.js directory and run Bundler’s install command.

$ cd asciidoctor.js
$ bundle install

You’re now ready to build asciidoctor.js.

Building asciidoctor.js

To build asciidoctor.js, run the Rake dist task from the root of the project.

$ rake dist

This command produces two files in the build directory:

opal.js

The Ruby runtime in JavaScript

asciidoctor.js

The JavaScript port of Asciidoctor

You may notice that these files are not an ideal size for loading in a browser. They gzip rather nicely, bringing the size of asciidoctor.js down from 550K to 90K. There are options in Opal to generate more efficient code, but they are causing problems at the moment. Once we sort out those issues, the size of the generated files should be quite acceptable.

You need to load both files into your JavaScript environment to use Asciidoctor. For instance, in an HTML page, add these two <script> tags (ideally at the bottom of the page).

<script src="opal.js"></script>
<script src="asciidoctor.js"></script>

You’ll see these scripts in action when you run the examples, described next.

Building and running the examples

To build the examples, run the Rake examples task from the root of the project:

$ rake examples

This command produces another JavaScript file, asciidoctor_example.js, in the build directory. This script includes:

  • A string that contains an AsciiDoc source document

  • A call to the Asciidoctor API to render the content of that string to HTML

  • An event listener that inserts the generated HTML into the page

All the JavaScript in that file was generated from a Ruby script by Opal.

Point your browser at build/asciidoctor_example.html. You should see the AsciiDoc Syntax Quick Reference document. The content on the page was rendered from AsciiDoc by asciidoctor.js when you loaded the page!

Using Asciidoctor in JavaScript

There are two ways to use the JavaScript version of Asciidoctor:

  1. Write code in Ruby that hooks into the native JavaScript environment, which Opal compiles into JavaScript

  2. Invoke the JavaScript APIs that Opal generates directly from JavaScript

Using Asciidoctor and the native JavaScript environment from Ruby

First, we’ll stuff some AsciiDoc data into a variable inside a Ruby script.

data = <<-EOS
= asciidoctor.js, AsciiDoc in JavaScript
Doc Writer <docwriter@example.com>

Asciidoctor and Opal come together to bring
http://asciidoc.org[AsciiDoc] to the browser!.

== Technologies

* AsciiDoc
* Asciidoctor
* Opal

NOTE: That's all she wrote!
EOS

Next, we invoke Asciidoctor in Ruby just as we normally would.

html_doc = Asciidoctor.convert(data, :safe => :safe,
  :attributes => %w(notitle! anchors imagesdir=./images))

We then use the global $window object provided by Opal to register a listener that inserts the rendered HTML document into the page.

$window.addEventListener 'DOMContentLoaded', proc {
  $document.getElementById('content').innerHTML = html_doc
}, false

The final step is to compile this Ruby code into JavaScript using the Opal compiler.

env = Opal::Environment.new
env.append_path 'examples'
compiled = env['asciidoctor_example'].to_s
File.open('build/asciidoctor_example.js', 'w') { |f| f << compiled }

When the asciidoctor_example.js script is loaded by the browser, the Ruby code (compiled as JavaScript) is executed, rendering the AsciiDoc document and inserting the result into the page.

You can also invoke Asciidoctor directly from JavaScript.

Using Asciidoctor from JavaScript

If you choose, you may use the Asciidoctor class that Opal generates directly from Ruby.

All Opal-compiled classes are stored under the Opal namespace. Ruby variables and methods on a class or object get prefixed with $. Thus, where you would execute Asciidoctor.convert in Ruby, you execute Opal.Asciidoctor.$convert in JavaScript.

var html_doc =Opal.Asciidoctor.$convert(
    "http://asciidoctor.org[*Asciidoctor*] " +
    "running on http://opalrb.org[_Opal_] " +
    "brings AsciiDoc to the browser!")

You would insert the rendered document into the page using the normal JavaScript DOM methods.

document.getElementById('content').innerHTML = Opal.Asciidoctor.$convert(
    "http://asciidoctor.org[*Asciidoctor*] " +
    "running on http://opalrb.org[_Opal_] " +
    "brings AsciiDoc to the browser!")

Passing the options Hash to the render method requires a little bit of Opal voodoo.

Opal.hash2(['attributes'], {'attributes': ['notitle!']})

Resources and help

For more information:

If you have questions or would like to help develop this project, please join the Asciidoctor discussion list.

Copyright © 2013 Dan Allen. Free use of this software is granted under the terms of the MIT License.

See the LICENSE file for details.