self.port.on('RENDER_SANITIZED_HTML', function(message) {
  showHTML(message.html); 
});

var asciidocify = {
  load: function() {
    var contentType = document.contentType;
    var regexpAdFile = /\.a(sciidoc|doc|d|sc)$/i;
    var isAsciiDocFile = regexpAdFile.test(document.location);
    var isHTMLContent = contentType && (contentType.indexOf('html') > -1);
    if (isAsciiDocFile && !isHTMLContent) {
      convertSanitizeAndRender();
    }
  }
};

var ASCIIDOCTOR_OPTIONS = Opal.hash2(['backend', 'safe', 'attributes'], {
  'backend': 'xhtml',
  'safe': 'server',
  'attributes': ['showtitle', 'toc!', 'toc2!']
});

/**
 * Convert AsciiDoc content as HTML and render in web view
 */
function convertSanitizeAndRender() {
  try {
    try {
      // if charset is not UTF-8, try techniques to coerce it to UTF-8
      // likely used only for local files
      if (document.characterSet.toUpperCase() != 'UTF-8') {
        try {
          // this technique works if all characters are in standard ASCII set
          // see: http://www.ascii-code.com
          sanitizeAndShowHTML(convertToHTML(decodeURIComponent(escape(document.firstChild.textContent))));
        } catch (decodeError) {
          // XMLHttpRequest responseText is UTF-8 encoded by default
          var xhr = new XMLHttpRequest();
          xhr.open('GET', window.location.href, true);
          xhr.onload = function (evt) {
            if (xhr.readyState === 4) {
              // NOTE status is 0 for local files (i.e., file:// URIs)
              if (xhr.status === 200 || xhr.status === 0) {
                sanitizeAndShowHTML(convertToHTML(xhr.responseText));
              } else {
                console.error('Could not read AsciiDoc source. Reason: [' + xhr.status + '] ' + xhr.statusText);
              }
            }
          };
          xhr.onerror = function (evt) {
            console.error(xhr.statusText);
          };
          xhr.send();
        }
      } else {
        sanitizeAndShowHTML(convertToHTML(document.firstChild.textContent));
      }
    } catch (e) {
      showErrorMessage(e.name + ' : ' + e.message);
    }
  }
  catch (e) {
    showErrorMessage(e.name + ' : ' + e.message);
  }
}

/**
 * Convert AsciiDoc to HTML
 * @param content
 * @return {*}
 */
function convertToHTML(content) {
  emptyBody();
  return Opal.Asciidoctor.$convert(content, ASCIIDOCTOR_OPTIONS);
}

/*
 * Pass the HTML through sanitization, then show it.
 *
 * @param html The HTML generated by Asciidoctor to sanitize, then show in the web view.
 */
function sanitizeAndShowHTML(html) {
  self.postMessage({ html: html });
}

/*
 * Show the HTML.
 *
 * @param html The sanitized HTML to show in the web view.
 */
function showHTML(html) {
  appendStyles();
  appendContent(html);
}

/**
 * Show error message
 * @param message The error message
 */
function showErrorMessage(message) {
  var html = '<h2>AsciiDoc conversion failed!</h2>' + "\n" + '<p>' + message + '</p>';
  emptyBody();
  appendContent(html);
}

/**
 * Clear all nodes from body of document.
 */
function emptyBody() {
  var node = document.body;
  while (node.hasChildNodes()) {
    node.removeChild(node.lastChild);
  }
}

/**
 * Append CSS files for styling the generated HTML.
 */
function appendStyles() {
  var asciidoctorLink = document.createElement('link');
  asciidoctorLink.rel = 'stylesheet';
  asciidoctorLink.id = 'asciidoctor-style';
  asciidoctorLink.href = 'resource://asciidoctor-firefox-addon-at-asciidoctor-dot-org/asciidoctorjslivepreview/data/asciidoctor.css';
  document.head.appendChild(asciidoctorLink);
}

/**
 * Append fragment to document body.
 */
function appendContent(html) {
  var contentDiv = document.createElement('div');
  contentDiv.id = 'content'
  contentDiv.innerHTML = html;
  document.body.appendChild(contentDiv);
}

@@ -599,21 +599,68 @@
 ', '
-toc!', 'toc2!
+platform=opal', 'platform-opal', 'env=browser', 'env-browser
 '%5D%0A%7D

set implicit attributes; no need to disable toc