Giter Site home page Giter Site logo

jirutka / asciidoctor-templates-compiler Goto Github PK

View Code? Open in Web Editor NEW
4.0 4.0 3.0 84 KB

Compile templates-based Asciidoctor converter (backend) into a single Ruby file

License: MIT License

Ruby 100.00%
asciidoctor converter slim-template asciidoctor-converter

asciidoctor-templates-compiler's Introduction

Asciidoctor Templates Compiler

CI Status Test Coverage Codacy Code quality Gem Version

This tool allows to precompile Slim templates into Ruby code and assemble them into a single-file pure Ruby converter (backend).

Installation

Add this line to your application’s Gemfile:

group :development do
  gem 'asciidoctor-templates-compiler', '~> 0.7.0'
end

or to your gemspec:

s.add_development_dependency 'asciidoctor-templates-compiler', '~> 0.7.0'

and then execute:

$ bundle install

Usage

The main entry point is method Asciidoctor::TemplatesCompiler::Slim#compile_converter (for Slim) that accepts the following keyword arguments.

backend_info

A hash of keys for backend_info: basebackend, outfilesuffix, filetype, htmlsyntax, supports_templates.

class_name

Full name of the converter class to generate (e.g. My::HTML::Converter). This argument is required.

delegate_backend

Name of the backend (converter) to use as a fallback for AST nodes not supported by your converter. If not specified (default), no fallback will be used and converter will raise NoMethodError when it try to convert an unsupported node.

engine_opts

A Hash of options to pass into the templating engine that compiles templates into Ruby code.

ignore_convert_opts

Ignore (i.e. do not set as local variables) options passed to the #convert method (i.e. to the templates). This is needed only for Opal.

output

An output stream (IO object like opened file, $stdout, …) to write the generated converter into. Default is StringIO.new (it’s the return value of #compile_converter).

pretty

Enable pretty-formatting of the generated Ruby code (generated by Slim/Temple)? Default is false.

register_for

An array of backend names that the generated converter should be registered in Asciidoctor to handle. Default is empty.

templates_dir

Path of the directory where to look for templates (*.slim files not starting with _, in the case of Slim) and (optional) helpers.rb. This argument is required.

Examples

Minimal example
require 'asciidoctor-templates-compiler'

File.open('converter.rb', 'w') do |file|
  Asciidoctor::TemplatesCompiler::Slim.compile_converter(
      templates_dir: 'data/templates',
      class_name: 'ShinyHtml::Converter',
      delegate_backend: 'html5',
      register_for: ['shiny-html'],
      backend_info: {
        basebackend: 'html',
        outfilesuffix: '.html',
        filetype: 'html',
      },
      pretty: true,
      output: file)
end
Example of usage in Rakefile
#!/usr/bin/env rake

CONVERTER_FILE = 'lib/asciidoctor/shiny_html/converter.rb'
TEMPLATES_DIR = 'data/templates'

namespace :build do

  file CONVERTER_FILE, [:mode] => FileList["#{TEMPLATES_DIR}/*"] do |t, args|
    require 'asciidoctor-templates-compiler'

    File.open(CONVERTER_FILE, 'w') do |file|
      $stderr.puts "Generating #{file.path}."
      Asciidoctor::TemplatesCompiler::Slim.compile_converter(
          templates_dir: TEMPLATES_DIR,
          class_name: 'Asciidoctor::ShinyHtml::Converter',
          delegate_backend: 'html5',
          register_for: ['shiny-html'],
          backend_info: {
            basebackend: 'html',
            outfilesuffix: '.html',
            filetype: 'html',
          },
          pretty: (args[:mode] == :pretty),
          output: file)
    end
  end

  namespace :converter do
    desc 'Compile Slim templates and generate converter.rb (pretty mode)'
    task :pretty do
      Rake::Task[CONVERTER_FILE].invoke(:pretty)
    end

    desc 'Compile Slim templates and generate converter.rb (fast mode)'
    task :fast do
      Rake::Task[CONVERTER_FILE].invoke
    end
  end

  task :converter => 'converter:pretty'
end

task :build => 'build:converter:pretty'

task :clean do
  rm_rf CONVERTER_FILE
end

You can also look into asciidoctor-html5s for a real-world example including integration with Asciidoctor::DocTest.

Opal Caveats

The generated converter code can be transpiled into JavaScript using Opal. However, there’s one feature that is known to not work: passing options to the #convert method.

Consider the following example:

toc.html.slim:
nav id='toc'
  = converter.convert document, 'outline', toclevels: 5
outline.html.slim:
- toclevels ||= document.attr('toclevels').to_i

Variable toclevels in outline.html.slim should be initialized to 5 when this template is called from the toc.html.slim template. This is implemented using Kernel#binding and Binding#local_variable_set which is not supported by Opal. In such case you get exception like this:

RuntimeError: node_modules/opal-runtime/src/opal.js
         throw exception;
         ^

binding: undefined method `binding` for [some Asciidoctor class]

Unfortunately I don’t know how to implement this feature without using Binding, but you can use the following workaround.

Enable ignore_convert_opts (see Usage) to remove the code calling Kernel#binding from the converter. The options will be still passed, but not binded to the template local variables. If you examine the generated code, you can see that the options are passed to the convert methods via argument named opts. You can exploit this fact and do something like:

outline.html.slim:
- toclevels = opts[:toclevels] || document.attr('toclevels').to_i

License

This project is licensed under MIT License. For the full text of the license, see the LICENSE file.

asciidoctor-templates-compiler's People

Contributors

ggrossetie avatar jeffkreeftmeijer avatar jirutka avatar obilodeau avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

asciidoctor-templates-compiler's Issues

Convert#convert method can be called without opts

Here's the stacktrace I get when using the supports_templates:

Traceback (most recent call last):
	14: from /home/guillaume/.rvm/gems/[email protected]/bin/ruby_executable_hooks:24:in `<main>'
	13: from /home/guillaume/.rvm/gems/[email protected]/bin/ruby_executable_hooks:24:in `eval'
	12: from /home/guillaume/.rvm/gems/[email protected]/bin/asciidoctor-revealjs:23:in `<main>'
	11: from /home/guillaume/.rvm/gems/[email protected]/bin/asciidoctor-revealjs:23:in `load'
	10: from /home/guillaume/workspace/opensource/asciidoctor/asciidoctor-reveal.js/bin/asciidoctor-revealjs:18:in `<top (required)>'
	 9: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/cli/invoker.rb:111:in `invoke!'
	 8: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/cli/invoker.rb:111:in `each'
	 7: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/cli/invoker.rb:128:in `block in invoke!'
	 6: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `convert_file'
	 5: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `open'
	 4: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `block in convert_file'
	 3: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:118:in `convert'
	 2: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:951:in `convert'
	 1: from /home/guillaume/.rvm/gems/[email protected]/gems/asciidoctor-2.0.10/lib/asciidoctor/converter/composite.rb:28:in `convert'
/home/guillaume/workspace/opensource/asciidoctor/asciidoctor-reveal.js/lib/asciidoctor-revealjs/converter.rb:168:in `convert': undefined method `empty?' for nil:NilClass (NoMethodError)

https://github.com/asciidoctor/asciidoctor/blob/32a269e71723ba10537a13b2b3dfa611b0131566/lib/asciidoctor/document.rb#L951

Asciidoctor::Converter:Base#handles? method always return false

Here's the implementation of the Asciidoctor::Converter:Base#handles method:

def handles? transform
  respond_to? %(convert_#{transform})
end

When using supports_templates, Asciidoctor will create a CompositeConverter that uses the handles method to find a converter for the specified "transform".
Since the methods are not prefixed by convert_ the handles? method will always returns false.

If we want to stay backward compatible with Asciidoctor 1.5.8, I think we should override the handles? method. Otherwise we should prefix the "convert" methods by convert_.

What do you think?

Engine options doesn't give intended results

Trying to use pretty: true output with Slim in Asciidoctor reveal.js doesn't give intended result.

Adding to the build Rakefile task:

      engine_opts: {
        generator: generator,
        pretty: true,
      }.

Then building the template and running it still gives packed HTML output.

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" /><title>Source Code with Highlight.JS</title><link rel="stylesheet" href="reveal.js/css/reset.css" /><link rel="stylesheet" href="reveal.js/css/reveal.css" /><link rel="stylesheet" href="reveal.js/css/theme/black.css" id="theme" /><!--This CSS is generated by the Asciidoctor-Reveal.js converter to further integrate AsciiDoc's existing semantic with Reveal.js--><style type="text/css">.reveal div.right {
  float: right;
}

But source should look like: https://github.com/asciidoctor/asciidoctor-reveal.js/blob/35b2bfadd34711c6b62d6f7e013b80b9b501d621/templates/document.html.slim#L1

Also a lot of new warnings are generated:

WARNING: Compiled template 'templates/toc.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/open.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/paragraph.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/verse.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/dlist.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_footnote.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/image.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_break.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/quote.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_indexterm.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/pass.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/table.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/document.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_callout.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/notes.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_image.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/video.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/literal.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/floating_title.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/embedded.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/sidebar.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/outline.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/listing.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_kbd.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/section.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/example.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_button.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_menu.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/audio.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/stem.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/olist.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_anchor.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/admonition.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/inline_quoted.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/ulist.html.slim' references constant ::Temple::Utils
WARNING: Compiled template 'templates/colist.html.slim' references constant ::Temple::Utils

I wasn't sure if the issue was here or upstream to be honest. Found this: https://github.com/asciidoctor/asciidoctor/blob/master/lib/asciidoctor/converter/template.rb#L33

Guidance appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.