Closed LightGuard closed 4 years ago
I'm thinking more like we will have template "packs" which you bundle into the extension as separate local JavaScript files. The extension can then load the file appropriate for the backend. For instance, we might have deckjs-backend.js, which compiles the templates for deck.js into a single JavaScript file.
So far, we only know how to compile ERB templates into JavaScript code. I don't see any reason why support can't be added in Opal for Haml or Slim too...but we'd have to do some exploration there.
Related to https://github.com/opal/opal/issues/339 ?
I agree with Anders on the deck.js backend idea. And a generalized solution as discussed here sounds like a good approach.
AsciiDoc is becoming more integrated with 'executable code' for "live tech documents" like what Neo Technology is doing with the Neo4j GraphGist format as an extension of GitHub's Gist feature. Being able to author such "live" documents in projected slide format for classroom/boardroom presentations will be most valuable. I believe this is the kind of value that could drive lots of expanded use of AsciiDoc.
For Haml there is an implementation in JavaScript (Node.js) https://github.com/creationix/haml-js
I think we would be better off using a JavaScript-based template language like Jade. In general, the goal is to cater to the native environment where it's used as much as possible. Wdyt?
All we need to do is make sure we can recognize & load Jade templates.
Of course, we can still support templates written in Haml too. I'm definitely not saying we shouldn't. Just that we should also do the platform native stuff like Jade in this case.
I think we would be better off using a JavaScript-based template language like Jade. In general, the goal is to cater to the native environment where it's used as much as possible. Wdyt?
You mean rewrite haml and slim templates in Jade ?
All we need to do is make sure we can recognize & load Jade templates.
We will need to load Jade templates in Asciidoctor (ruby) when running in an Opal environment right ?
Jade is almost exactly like slim. You may be able to change the extension and just use them.
You could also look at mustache/handlebars. On Sat, Nov 15, 2014 at 08:38 Guillaume Grossetie notifications@github.com wrote:
I think we would be better off using a JavaScript-based template language like Jade. In general, the goal is to cater to the native environment where it's used as much as possible. Wdyt?
You mean rewrite haml and slim templates in Jade ?
All we need to do is make sure we can recognize & load Jade templates.
We will need to load Jade templates in Asciidoctor (ruby) when running in an Opal environment right ?
— Reply to this email directly or view it on GitHub https://github.com/asciidoctor/asciidoctor.js/issues/5#issuecomment-63176247 .
You mean rewrite haml and slim templates in Jade ?
There are two needs going on here.
As Jason suggested, we may be able to get away with using the Slim templates with Jade...or at least get some reuse out of them.
The reason I suggest using Jade is so that we get back to the native JavaScript environment as soon as possible so Asciidoctor.js doesn't feel weird to people using it as just another JavaScript library.
There's now an implementation of custom templates in AsciidocFX. See https://github.com/asciidocfx/AsciidocFX/blob/master/src/main/resources/public/js/asciidoctor-reveal.js.
@rahmanusta, do you have the Ruby source available for the asciidoctor-reveal.js file and would you be willing to contribute a generic version of the template converter for JavaScript to asciidoctor.js?
@mojavelinux Yes, I am willing to contribute a generic version of the template converter to asciidoctor.js.
I created converter base classes in Ruby and after, continued with pure JavaScript. I will do a poc and will give and share more detail for this issue.
Great! We'd really appreciate that @rahmanusta!
Thanks Dan. I did a prework for template converter. please follow this issue https://github.com/asciidocfx/asciidoctor.js-reveal-demo/issues/1
What is the status of this integration ? Can we now use the jade or haml backend with asciidoctor.js ?
As we can't use the non built-in backends with asciidoctor.js, then we should catch the following error to display a message like "Not yet supported".
options used :
backend: 'revealjs'
template_dir: '/Users/chmoulli/Code/github/asciidoctor/asciidoctor-backends/slim'
Result
/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/node_modules/opal-runtime/src/opal.js:4627
throw exception;
^
TemplateConverter: uninitialized constant Asciidoctor::Converter::Factory::TemplateConverter
at Opal.defs.TMP_1 [as $new] (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/node_modules/opal-runtime/src/opal.js:4853:15)
at ːconst_missing (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/node_modules/opal-runtime/src/opal.js:2647:50)
at ːconst_get (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/node_modules/opal-runtime/src/opal.js:2624:19)
at Opal.get (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/node_modules/opal-runtime/src/opal.js:137:24)
at e.b.defn.H [as $create] (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/dist/npm/asciidoctor-core.min.js:220:170)
at l.b.defn.wa [as $create_converter] (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/dist/npm/asciidoctor-core.min.js:378:500)
at l.b.defn.oa [as $update_backend_attributes] (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/dist/npm/asciidoctor-core.min.js:373:322)
at l.b.defn.F [as $initialize] (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/dist/npm/asciidoctor-core.min.js:345:287)
at Opal.defn.TMP_4 [as $new] (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/node_modules/opal-runtime/src/opal.js:3140:23)
at module_constructor.b.defn.d [as $load] (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/dist/npm/asciidoctor-core.min.js:699:47)
at module_constructor.b.defn.g (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/dist/npm/asciidoctor-core.min.js:703:90)
at module_constructor.b.defn.l (/Users/chmoulli/.nvm/versions/node/v6.3.1/lib/node_modules/litoria/node_modules/asciidoctor.js/dist/npm/asciidoctor-core.min.js:710:314)
It's now possible to use custom templates written in Jade/Pug using https://github.com/asciidoctor/asciidoctor-template.js
I still need to write some documentation to explain how to use it (and/or create a sample project).
Please note that you can also use https://github.com/s-leroux/asciidoctor.js-pug/
So far, we only know how to compile ERB templates into JavaScript code.
Do you have a sample code somewhere?
I think we should support it out-of-the-box (at least for Node) with a few optional dependencies on the most popular template engines in JavaScript. Of course it should be extensible so if someone wants to use another template engine it should be possible.
In my opinion, it would be valuable to be able to use the -T
option:
$ npm init -y
$ npm install @asciidoctor/cli pug
$ ./node_modules/.bin/asciidoctor -T /path/to/pug/templates document.adoc
Maybe we should support templates defined as JavaScript file, for instance:
/path/to/js/templates/image.js
module.exports = (node) => `<div class="image ${node.getRoles().join(' ')}"><img src="${node.getImageUri(node.getAttribute('target'))}"/></div>`
So far, we only know how to compile ERB templates into JavaScript code.
That's actually straightforward, Opal can compile ERB templates. I've map the $compile
method in the latest version of the opal-compiler
:
const result = ERB.compile('The value of x is: <%= x %>');
You can use this snippet of code to convert a list of ERB templates:
$ npm i opal-compiler glob
const ospath = require('path')
const fs = require('fs')
const ERB = require('opal-compiler').ERB
const glob = require('glob')
glob('/path/to/templates/**.html.erb', function (err, files) {
for (file of files) {
const content = fs.readFileSync(file, 'utf-8')
const basename = ospath.basename(file, '.html.erb');
const dirname = ospath.dirname(file)
console.log(`compiling ${file}...`)
const result = ERB.compile(content, basename)
fs.writeFileSync(`${dirname}/${basename}.html.erbjs`, result, 'utf-8')
}
})
And then we can use the "erbjs" templates using a custom converter:
const asciidoctor = require('@asciidoctor/core')()
const glob = require('glob')
class ERBTemplateConverter {
constructor (templateFiles) {
// "erb.js" will be included in the next version of the Opal runtime package.
// For now, we need to copy it from https://github.com/opal/opal-cdn/blob/gh-pages/opal/1.0.0/erb.js
require('./erb.js')
for (let file of templateFiles) {
require(file)
}
this.templates = {}
const paths = Opal.Template['$paths']()
for (let path of paths) {
this.templates[path.replace(/^block_/, '')] = Opal.Template['$[]'](path)
}
this.baseConverter = asciidoctor.Html5Converter.create()
}
convert (node, transform, opts) {
const name = transform || node.node_name
const template = this.templates[name]
if (template) {
return template.$render(node)
}
return this.baseConverter.convert(node, transform, opts)
}
}
async function getTemplates (templateDirectory) {
return new Promise((resolve, reject) => {
glob(`${templateDirectory}/**.html.erbjs`, function (err, files) {
if (err) {
return reject(err)
}
return resolve(files);
})
})
}
(async () => {
const templates = await getTemplates('/path/to/templates')
asciidoctor.ConverterFactory.register(new ERBTemplateConverter(templates), ['html5'])
asciidoctor.convertFile('sample.adoc', { to_dir: './build', mkdirs: true, safe: 'safe' })
})()
At some point we might support ERB templates transpiled to JavaScript out-of-the-box.
I think we need to add a template engines registry because, as far as I know, Node ecosystem does not have a generic interface to use multiple Node template engines.
The template engines registry will be global. The API might look like:
class PugTemplateEngine {
constructor() {
this.pug = require('pug')
}
compile(file) {
return this.pug.compileFile(file)
}
}
asciidoctor.TemplateEngineRegistry.register(new PugTemplateEngine(), ['pug', 'jade'])
We register a template engine with a list of file extensions (here .pug
and .jade
). For a given file, it should return a "render" function that takes a JSON as an argument. The "render" function will be called as follows:
render({node: node, opts: opts, helpers: self.helpers})
Another example:
const fs = require('fs')
class NunjucksTemplateEngine {
constructor() {
this.nunjucks = require('nunjucks')
}
compile(file) {
return this.nunjucks.compile(fs.readFileSync(file, 'utf8'))
}
}
asciidoctor.TemplateEngineRegistry.register(new NunjucksTemplateEngine(), ['njk'])
Not exactly sure how we'll get around the browser sandbox, but I'm sure something can be figured out.