Asciidoctor Templates Compiler
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 isStringIO.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
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
#!/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:
nav id='toc'
= converter.convert document, 'outline', toclevels: 5
- 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:
- 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.