asciidoctor / asciidoctor-backends

Backends (i.e., templates) for Asciidoctor, a Ruby port of AsciiDoc.
http://asciidoctor.org
Other
65 stars 73 forks source link

Create a backend for reveal.js presentations #12

Closed mojavelinux closed 10 years ago

mojavelinux commented 11 years ago

Create a backend for reveal.js presentations.

reveal.js: http://lab.hakim.se/reveal-js/

Keep in mind that we want to try to align the different presentation backends (deck.js, reveal.js, dzslides, etc) so that the same AsciiDoc source file will work using any one of them (within reason).

Also, each backend should be create in its own git repository to make collaboration and releases easier.

jordanmccullough commented 11 years ago

Having dabbled with RevealJS, I'd definitely like to work on/contribute to this endeavor.

lordofthejars commented 11 years ago

Cool, I implemented the deck.js backend so if you have any question feel free to ask me here or by using http://discuss.asciidoctor.org/

mojavelinux commented 11 years ago

@jordanmccullough That's great to hear! We've got a reveal.js pro in the house! Woot!

Although you probably don't need any hints, I know @paulrayner has played around with a reveal.js backend for Asciidoctor for one (or more) of his presentations. However, he was extending the built-in classes instead of using Tilt. Custom backends should be done using Tilt because the built-in classes should be treated as private.

My one word of advice is to aim for the simplest possible syntax (roles, options, etc) that will work. @jordanmccullough you probably don't need any convincing on that coming from Markdown. Hopefully you'll find the AsciiDoc syntax is a good fit for achieving the type of hierarchical organization of slides that you have in HydeSlides.

Happy hacking!

buuhsmead commented 11 years ago

Writing a revealjs backend right now. Using tilt and haml. Never really used haml/titlt/revealjs and have to learn the structure asciidoctor calls the haml files. Created a subdirectory asciidoctor-backends/haml/revealjs and started with document.html.haml. Is that the right direction?

mojavelinux commented 11 years ago

@buuhsmead Excellent!

I recommend starting with either haml or tilt (I see you chose haml, which is fine). It's easy to then port it to slim. Using multiple engines in the backend doesn't really benefit users, but it gives people interested in hacking on it the raw material if they prefer to use one engine over another. To be honest, I'm still debating with myself what the best approach is.

You have the right idea to get started:

I'll give a brief overview of the object model that is available for each template (hopefully so it makes its way into some official documentation soon).

Each template represents one type of document node, similar to an XML DOM node. There are three types of nodes:

The first template to be invoked is document.html.. When the content variable (technically a method) of a node is referenced, the rest of the document is rendered by walking the document recursively and rendering each node.

You can think of the template as a single method call on the node object. Within the template, you have access to all the instance variables and instance methods of the node, just as you would inside a method call.

For example, the following line invokes the content() method on the node:

=content

Each node holds the following common information:

Block nodes hold the following additional information:

* In a list block, the content is a collection of the list items.

Inline nodes hold the following additional information:

The following table shows some of the instance variables and instance methods you'll use in a template:

Name Example(s) Description
content content Renders the children of this node (if any) and returns the result.
id @id The id assigned to the block or nil of no id is assigned.
document @document A reference to the current document (and all of its nodes).
attr(name, default = nil) attr('language')
attr('toc-class', 'toc')
@document.attr('icons', 'font')
Retrieves the value of the specified attribute in the attributes hash, using the name as a key. If the name is written as a symbol, it will be automatically converted to a string before lookup.
attr?(name, match = nil) attr?('icons')
attr?('toc-placement', 'auto')
Checks whether the specified attribute exists in the attribute hash, using the name as the key. If the name is written as a symbol, it will be automatically converted to a string before lookup. If a match is provided, additionally checks whether the attribute value matches the specified value.
style @style Retrieves the style (qualifier) for a block. If the block does not have a style, nil is returned.
role role A convenience method that returns the role attribute for the block, or nil if the block does not have a role.
role? role? A convenience method to check whether the block has the role attribute.
option?(name) option?('loop') A convenience method to check whether the specified option attribute (e.g., loop-option) is present.
title title Retrieves the title of the block with normal substitutions (escape XML, render links, etc) applied.
title? title? Checks whether a title has been assigned to this block. This method does not have side effects (e.g., checks for existence only, does not apply substitutions)
image_uri(path) image_uri(attr 'target') Converts the path into an image uri (reference or embedded data) to be used in an HTML img tag. Applies security restrictions, cleans path and can embed image data if :data-uri: attribute is enabled on document. Always use this method when dealing with image references. Relative image paths are resolved relative to document directory unless overridden using :imagesdir:
icon_uri(path) icon_uri(attr 'target') Same as image_uri except it specifically works with icons. By default, it will look in the subdirectory images/icons, unless overridden using :iconsdir:
media_uri(path) media_uri(attr 'target') Similar to image_uri, except it does not support embedding the data into the document. Intended for video and audio paths.
normalize_web_path(path, relative_root) normalize_web_path(attr('stylesheet'), attr('stylesdir', '')) Joins the path to the relative_root and normalizes parent and self references. Access to parent directories may be restricted based on safe mode setting.
normalize_system_path(path, relative_root, jail) normalize_system_path(attr('stylesheet'), attr('stylesdir', ''), true) The most critical method to ensure proper security. Joins the path to the relative_root and normalizes parent and self references. Access to parent directories may be restricted based on the safe mode setting. This method is extremely careful about assembling safe paths.

In both Haml and Slim, you can assign an array to an HTML attribute and it will automatically be compacted (empty elements removed) and joined into a space-separated list.

For example:

%div{:id=>@id, :class=>['admonitionblock', (attr :name), role]}

Assuming id=foobar, name=warning, role=nil, the following element is produced:

<div id="foobar" class="admonitionblock warning">

If you assign a single value to an attribute, and the value is nil, the attribute will be excluded. Thus, if id is nil, then the output of the previous example would be:

<div class="admonitionblock warning">

The list block templates (block_olist, block_ulist and block_dlist) are responsible for handling their own direct children.

For example:

%ol{:class=>@style, :start=>(attr :start), :type=>(Asciidoctor::ORDERED_LIST_KEYWORDS[@style])}
  - content.each do |item|
    %li
      %p=item.text
      - if item.blocks?
        =item.content

Hopefully that gets you going. I'll post more information as it comes to mind.

mojavelinux commented 11 years ago

I have some additional notes on the following wiki page, though it's mostly just an outline:

https://github.com/asciidoctor/asciidoctor/wiki/APIs-for-Backend-Templates

mojavelinux commented 11 years ago

Here's a rough and partially complete list of attributes:

https://github.com/asciidoctor/asciidoctor/wiki/Catalog-of-Document-Attributes

mojavelinux commented 11 years ago

The best reference, atm, is the html5 backend in Haml. It's nearly feature complete to 0.1.4.preview.1.

https://github.com/asciidoctor/asciidoctor-backends/tree/master/haml/html5

jordanmccullough commented 11 years ago

@mojavelinux Those pieces of info are a great help. Thank you!

Contributions to @buuhsmead's efforts for the RevealJS backend are en route.

mojavelinux commented 11 years ago

Awesome @jordanmccullough!

mojavelinux commented 11 years ago

I've published a preview release of Asciidoctor 0.1.4. I recommend building the reveal.js backend against it as it has some improvements for making backend development easier. For example, you can now check for the existence of a role using role? and get a list of all roles using roles.

gem install asciidoctor --pre

I spoke to @jordanmccullough about speaker notes today. I think an admonition block + an ideal fit for this use case. Here's how I do it in dzslides:

[NOTE.speaker]
--
* AsciiDoc is easy to read in raw form.
* It's also easy to proof and edit.
* The punctuation was chosen to look like what it means.
* Only requires a text editor to read or write.
--

In the block_admonition.html.haml template you can check for this role using:

- if role? 'speaker'
  -# output HTML for speaker notes here
- else
  -# normal admonition stuff
mojavelinux commented 11 years ago

I wonder if role? should be has_role? and let role? check for an exact match. Thoughts?

paulrayner commented 11 years ago

I'm all for explicitness, so I vote for has_role? returning whether it has a role or not, assuming that's what you mean.

On Jul 6, 2013, at 5:49 PM, Dan Allen notifications@github.com wrote:

I wonder if role? should be has_role? and let role? check for an exact match. Thoughts?

— Reply to this email directly or view it on GitHubhttps://github.com/asciidoctor/asciidoctor-backends/issues/12#issuecomment-20563083 .

mojavelinux commented 11 years ago

Added: https://github.com/asciidoctor/asciidoctor/commit/34c91c7ee7abcbedb37f811c925da8bac411e858

mojavelinux commented 10 years ago

Some additional useful info for creating custom backends:

http://discuss.asciidoctor.org/How-can-we-pass-parameters-to-HAML-HTML5-backend-template-td1036.html#a1076

mojavelinux commented 10 years ago

Added by @cmoulliard with this commit: 18714c55fa7f55528918b4e8c4087fa8008e3aaa

We'll use separate issues to track enhancements.