incorporate reports with slidify
trinker opened this issue · comments
slidify is a terrific package that works with Rmd and Rnw to output to multiple html5 types. Here is a video over viewing the package. This package would fit very nicely with the reports package and appears to be very well developed.
Currently it is on github but Ramnathv plans to push to CRAN by the end of April-ish. When that happens I think it would be wise to incorporate it into reports in a fashion that maintains the reports way of integrating with RStudio in an efficient way (i.e., assumed working directories).
There may be a need to create wrapper functions for slidify that keep this in rune with the reports package (I think a frame work like r_
+ slidify function
would be easy for people familiar with slidify to change between).
Very exciting!
Additional info:
http://ramnathv.github.com/slidify/index.html
https://github.com/ramnathv/slidifyExamples
Note: reveal.js
and html5
are no longer going to be actively developed.
Yeah, I've been trying to follow slidify development. As far as I can tell, I don't see a clear way to create "increment" or "fragment" for arbitrary html elements. With reveal.js, you can easily make even svg
elements hidden/revealed, plus there's tremendous flexibility since you can also add/remove custom classes instead of just hide/reveal. For me, that's a pretty big limitation, and it's not exactly simple to add it on after the fact, especially when supporting as many different formats as slidify.
That is food for thought.
Perhaps I can make the frame work flexible for uses that does give the
option of reveal.js and html5 within the reports package but also allows
the user to efficiently switch to a slidify framework if they chose. I
think this may be the best approach. This could be an argument to
new_reports
and presentation
that can be set with a global option (and
will revert to a reports only frame work if not specified). Slidify
definitely has some nicieites that would be unwise to not harness but it
seems (as with most things) you give up some flexibility with convenience.
Thanks for your insight. Thoughts on the above proposal?
On Mon, Mar 18, 2013 at 12:22 AM, jamiefolson notifications@github.comwrote:
Yeah, I've been trying to follow slidify development. As far as I can
tell, I don't see a clear way to create "increment" or "fragment" for
arbitrary html elements. With reveal.js, you can easily make even svgelements hidden/revealed, plus there's tremendous flexibility since you can
also add/remove custom classes instead of just hide/reveal. For me, that's
a pretty big limitation, and it's not exactly simple to add it on after the
fact, especially when supporting as many different formats as slidify.—
Reply to this email directly or view it on GitHubhttps://github.com//issues/18#issuecomment-15038697
.
I have been following the comments on here and they are pretty useful. It is actually pretty straightforward to extend Slidify to allow attaching classes to arbitrary HTML elements. The trick is to come up with a specification that is easy to use, but at the same time will not conflict with regular usage.
I experimented with the following specification, which seems to work well. For example,
> - Point 1
> - Point 2
> - .highlight-red Point 3
will convert to
<ul class='incremental'>
<li class='fragment'>Point 1</li>
<li class='fragment'>Point 3</li>
<li class='fragment highlight-red'>Point 1</li>
</ul>
The fragment
class is added using jQuery as soon as it detects a <ul>
element with the class incremental
.
I am also considering the syntax used by kramdown
http://kramdown.rubyforge.org/syntax.html#inline-attribute-lists that allows classes and style to be added to arbitrary html elements. In essence, this is equivalent to extending markdown, and there is a strong view held by the community that more complicated things should be left to html. But, I believe something as simple as adding a class, can be left to markdown, and that is what I will be attempting.
Any feedback/thoughts on this are welcome.
Note to self: Remember to address this: ramnathv/slidify#178 (comment)
@ramnathv I like that addition. Will it be permanent?
I have also added the colors of the rainbow + brown to the reveal.css and reveal.min.css. Would it be possible to add these parameters as well?
So I added to reveal.css:
.red .reveal .state-background {
background: rgba( 255, 0, 0, 1 );
}
.orange .reveal .state-background {
background: rgba( 255, 165, 0, 1 );
}
.yellow .reveal .state-background {
background: rgba( 255, 255, 0, 1 );
}
.green .reveal .state-background {
background: rgba( 0, 128, 0, 1 );
}
.blue .reveal .state-background {
background: rgba( 0, 0, 255, 1 );
}
.indigo .reveal .state-background {
background: rgba( 75, 0, 130, 1 );
}
.violet .reveal .state-background {
background: rgba( 238, 130, 238, 1 );
}
.brown .reveal .state-background {
background: rgba( 139, 69, 19, 1 );
}
and I added to reveal.min.css:
.red .reveal .state-background{background:rgba(255,0,0,1)}.orange .reveal .state-background{background:rgba(255,165,0,1)}.yellow .reveal .state-background{background:rgba(255,255,0,1)}.green .reveal .state-background{background:rgba(0,128,0,1)}.blue .reveal .state-background{background:rgba(0,0,255,1)}.indigo .reveal .state-background{background:rgba(75,0,130,1)}.violet .reveal .state-background{background:rgba(238,130,238,1)}.brown .reveal .state-background{background:rgba(139,69,19,1)}
Would it be possible to add these or in some way dynamically control individual slide color?
- Yes, the addition will be permanent, once I convince myself that the API to do this is simple and robust.
- Yes. Slidify automatically adds any CSS files it finds in
assets/css
. In order to keepslidifyLibraries
updated, I regularly sync every framework from github. Hence, I don't like to add custom css files directly to the framework. The easiest way to add these to your presentation, is to create a css filereveal-reports-custom.js
and add it toPRESENTATION/assets/css
, after youauthor
the presentation. This way, these styles automatically get included when you slidify it.
It is easy to add arbitrary html attributes to slides. Everything in Slidify is controlled by templates. For example, each slide in RevealJS has the following template as default. So you can specify the data-state
to soothe
by adding ds:soothe
to the slide starter ---
. To better understand, here is an Rmd slide and the resulting HTML.
Rmd
--- ds:soothe .class1 .class2 key:value
## Slide Title
Slide body
*** =pnotes
This is a slide note.
HTML
<section class='class1 class2' data-state='soothe' key='value'>
<h2>Slide Title</h2>
<p>Slide body</p>
<aside class='notes'>
<p>This is a slide note.</p>
</aside>
</section>
There is a ton of work to be done in documenting these features more clearly. I guess, I have been more excited adding features, but will get around to creating better documentation.
Let me know if this is clear. I will push an updated version of the RevealJS example to SlidifyExamples. If you have a certain feature in mind, feel free to add it here on GitHub.
I was going to ask you what the advantages of slidify are over pandoc and then I started looking at the way you're doing things. I just spent an inordinate amount of time this weekend extending pandoc to support reveal.js, so I am intimately aware of how awesome it is to have such a modular design.
I would reconsider the syntax for vertical slides.
I'm not totally sure how you're defining slides. Does every slide need to be designated with "---"? Do vertical slides need to be designate "***"? I'm not sure I like that, but it has a certain clarity.
FWIW My fork of pandoc for reveal.js extends the pandoc notation, where headers following empty lines define slides. I turn level one headers into a (to-be) "stack" section and insert any contained level two headers into the stack. I'm not sure how simple a rule like this would be to implement in slidify, but it doesn't seem complicated.
It's a tradeoff. The explicit notation you use has a benefit of clarity, but it might make it different to move things around. Do you need both &vertical
and ***
designation for vertical slides?
One problem with the way I'm doing things is that it might seem opinionated about how things slides should be marked up (e.g. ALL slide headings in pandoc are rendered as <h1>
). However, I'm not sure that's a bad thing. Too much flexibility can let people make bad decisions and being stylistically inconsistent between slides is likely to just be distracting, so I kind of like the way pandoc (and I) do things.
I really like how aggressively you're adding new thing. I do think that your proposed format for new classes will get confusing, though. There are a couple of different strategies around. I think Maruku's makes some sense, and in the pandoc group someone put together a pretty comprehensive proposal for attribute syntax.
One thing that I think would be great is the ability for users to insert "hooks" into the processing, similar to the way knitr
does. This might, for example, make it super easy to customize the way "incremental" items are created.
Just testing a few things out, it looks like the markdown
package you're using supports embedding markdown inside html, which pandoc told me is not standard.
Does github do it? Apparently not:
*bold?*
I really like the way you're doing things, and in particularly, how things like the markdown
package at least appear to make it easy to add new extensions. Just playing around with pandoc, I was concerned with how conservative they seem in terms of supporting new syntax. I can appreciate that need for a general tool, but it's not clear to me how much you can support the features required to make a really great presentation while practically requiring that the input document be convertible to so many other formats.
I would, however, suggest to try to keep the markup as separate from the rest of the code as possible. In terms of specifics, I like the idea of pseudo-html syntax for some markup extensions, like
- <%.highlight-red%>Point 3<%/>
- Point 3 <%.highlight-red%/>
- <%Point 3%.highlight-red/>
But at the same time, that feels like it might be a little verbose. It's also pretty ugly and makes writing markdown much less aesthetically appealing. This gist of the proposal linked above is something like
- {.highlight-red} Point 3
or
- Point 3 {.highlight-red}
depending on the syntactic ambiguity. Personally, I think appending this makes it much less distracting. This is also pretty close to attribute syntax used elsewhere.
Thanks for taking the time to explore Slidify and provide some great feedback. Let me try to address the issues you have raised here, briefly.
A slide is explicitly designated by three dashes ---
. A slide can contain blocks, which are designated by ***
. I chose this syntax for clarity, and the fact that even in plain markdown, these designators will be rendered as a horizontal rule.
The slide designator can be followed by arbitrary attributes, which are essentially key values pairs of the form key:value
. Common attributes like id
and class
have abbreviated keys #
and .
Slidify works by parsing a slide into metdata and content, and then running the parsed data through templates. I chose markdown
for markup, and mustache
for templates, since it makes it easy to replicate my approach in other scripting languages python
, ruby
, javascript
etc. Moreover, I like the simplicity and elegance of markdown
and mustace
.
The idea of this design was to make it possible to support multiple HTML5 slide frameworks, all of which seem to be doing the same thing in a myriad of different ways. Now RevealJS was one of the odd-ball frameworks which supported vertical slides, which required nesting. The easiest way to achieve this in Slidify was to use slide blocks for the nested vertical slides, and then use a template to render them correctly.
Here is the slide template for vertical slides. You will notice that it loops through slide blocks and puts them between sections. Each block can contain its own metadata which allows me to do anything with them, that I can do with a slide. So, &vertical
specifies that the slide use the vertical slide template, and the ***
define the slides themselves.
<section>
<section class='{{slide.class}}' data-state='{{slide.ds}}' id='{{slide.id}}'>
{{{ slide.header }}}
{{{ slide.content }}}
<aside class='notes'>
{{{ slide.pnotes }}}
</aside>
</section>
{{# slide.blocks }}
<section class='{{class}}' data-state='{{ds}}' id='{{id}}'>
{{{ html }}}
<aside class='notes'>
{{{ pnotes.html }}}
</aside>
</section>
{{/ slide.blocks }}
</section>
The design choices I made were essentially to create a flexible framework. It is easy to write pre-processors that would allow you to use Slidify the pandoc
way. For example, if you always use h1
tags for slide titles, you can write a simple script that prepends every h1
markdown tag with a ---
and then run Slidify. Another way to ensure consistency is through tweaking the base slide template, where you can force slide titles to be rendered as h1s independent of the header level specified by the user.
So to sum up, Slidify is an general unopinionated framework, that can be extended in multiple ways. For example, after I created Slidify, I realized that a blog is no different from a slide deck. So with some tweaks, I was able to use Slidify to generate a blog from R markdown
I like your suggestions of keeping the markup separate from the rest of the code. I will experiment with using {.highlight-red}
as class specifier. I believe that markdown should have simple syntax and if we are bending it too much, it is much better to just write html directly. So, I will be cautious as to what should be added to markdown.
Please keep the suggestions coming.
Regarding pandoc
, it is a swiss-army-knife with capabilities significantly beyond what Slidify can do. I created Slidify since I wanted to use other slide frameworks, and hacking pandoc
was turning out to be a nightmare given my lack of familiarity with haskell.
For an R user, the advantage of Slidify is easy installation and interplay with other R packages, and the knitr
integration.
That sounds fantastic! I had not realized the slide "block" was a more general concept. I don't see any other templates (only checked dzslides and deck) using these slide blocks. What happens in other frameworks?
Frankly, the knitr
integration is nice, but I think the big thing speaking to me right now is more the relative inflexibility of pandoc in comparison. Everything in pandoc makes sense and given my prior knowledge of haskell, it wasn't especially difficult, but I'm just not sure it makes sense to have to compile code to build a document, especially for slides, where you might be doing a fair amount of playing around. Thinking of latex: it's plenty of a disconnect to have to compile a document before seeing it, but with pandoc, you essentially need to compile your latex class/style before compiling your document. Also, there's a lot of "infrastructure" type work for separating slides etc. that it seems difficult to e.g. write a plugin that "just" adds a bit of new syntax. You could pre-process the document, but then you have to do all your own parsing, etc.
Compare this with knitr
's hooks, where it's brain-dead simple to customize how anything is processed. I was editing the latex makefile to support knitr
and it took about two lines of code to print out all the generated graphics filenames so I could store dependencies.
Slide blocks are not a part of the default template for most frameworks (flowtimeJS and revealJS being the exceptions), although I use them extensively in creating custom layouts. I use blocks so that recurring html markup can be shifted to a layout file and I can keep the markdown clean. Layout can also inherit from other layouts, which adds another layer of flexibility. I will write about it some time.
I agree with your view of hooks. I need to think a little bit about how to make it work in a general way. If you have some suggestions, please post on the Slidify issues page. For now, my priority is to clean up the API, improve documentation and push the packages to CRAN so that they become easier to install. But, implementing hooks is certainly on my radar.
Here is an example of how I use blocks. Here is the Rmd and the resulting slide preview.
The layout is specified below. It allows me to separate layout from content. So for example, I use this pattern of a figure on the left and multiple choice questions on the right very often. So it made sense to abstract the design pattern into a layout and use it whenever required. The content of the block image
is accessed as slide.image.html
. The buttons you see on the page are abstracted into a partial {{> buttons }}
so that I could use them across other types of questions (checkbox, text etc.). Finally, the YAML front matter on the top says that this layout inherits from the default slide layout of the framework used, thereby allowing me to switch frameworks without having to rewrite the layout again.
---
layout: slide
---
<div class='row-fluid'>
<div class='span6'>
{{{ slide.image.html }}}
</div>
<div class='span6'>
<div class="quiz quiz-single well new">
{{{ slide.content }}}
{{> buttons }}
</div>
</div>
</div>
Whoa. That is neat.
I had to start a new comment because I was not prepared for how slick that was. I'm not entirely clear on how certain elements worked, particularly how the buttons partial used the block with ".explanation", but that's not important.
- The way you use
block
s to allow custom formatting for a section without departing from markdown is really smart. slide.image.html
is nice!- That layout is fantastic.
Everything I'm seeing makes me want to know more. So many of the slides frameworks I've looked at are all about pretty animations and all the fashionable aesthetics and such. You have clearly put a lot of thought into making sophisticated, modular, reusable layouts in a way that preserves as much of the cleanliness of markdown as possible.
The one thing I'll mention is that this makes me think block
is not the right concept for reveal.js stack
slides. The real power of block
elements is the flexibility of the layout, whereas, to me, the value of stack
s is largely easy navigation without buttons all over (e.g. many beamer themes).
I'm ashamed to admit that apparently I either hadn't read, or read and forgot about the customize section for slidify.
You might be right about blocks
not being the right approach for reveal.js
stack slides. I used it because it was the easiest way to nest sections within each other, which is required by reveal.js
to define vertical slides. Now that I think about it, an alternate approach would be to mark vertical slides with a special class, and then use jQuery
to modify the DOM and throw them into a parent <section>
element. I would welcome any suggestions you might have on how to implement this in a different way.
Let us continue this discussion on the issues page for Slidify.
Indeed. How are you identifying lists to be made incremental? I couldn't
find any references to "incremental" in slidify. Does the markdown library
do that?
Jamie Olson
On Tue, Mar 19, 2013 at 1:36 AM, Ramnath Vaidyanathan <
notifications@github.com> wrote:
Let us continue this discussion on the issues page for Slidify.
—
Reply to this email directly or view it on GitHubhttps://github.com//issues/18#issuecomment-15098366
.
Markdown does not support styling lists. I borrowed the idea from pandoc
, where a list specified like below is transformed to a list with the build class using regex. It is assuming that a user is very unlikely to want a list inside a blockquote, which I think is reasonable. For reveal.js
, which requires the <li>
items to also be tagged with fragment
, I just use a simple jQuery
statement to add fragment
to all <li>
items that are children of ul.build
or ul.incremental
.
I wish to keep the base syntax as close as possible to pandoc
, so that a user has the option to use pandoc
, especially for converting to pdf using beamer.
> - point 1
> - point 2
> - point 3
@trinker Here is a slide with the custom soothe styles you defined. You can find the source rmd, and the css here.
Let me know if this is what you were looking for.
Yes and I think it's easy to use (the approach in markdown you took). Would the user need to add the css themselves or will that be part of slidy? I am trying to work through it now (I am very new to html5) and didn't know where to add the css you linked. I tried calling it: slidify-reveal.css as you did and saving in the css folder. That yielded:
Quitting from lines 101-105 (index.Rmd)
Error in get(i, envir = from, inherits = FALSE) :
object '.Random.seed' not found
so obviously I didn't do it correctly.
Any css files you add to assets/css
would be automatically linked by slidify. The error you are getting seems to be because of knitr
caching. I would recommend removing the .cache
folder and slidifying again.
Perfect. That worked well. I'm getting the hang of this more. Do you think the user would need to add the .css in or is that something slidify would do? If not I think I'd have reports do it. I'm also thinking about using your examples and allowing the user to specificity a html5 slide type and that example would be used as the index.Rmd file. It's coming along nicely.
I dont understand what you mean by
.. the user would need to add the .css in
As long as you put your custom css files in assets/css
and they have a .css
extension, Slidify will automatically link it in your presentation.
I think I'll include it in reports. it makes it a little less flexible but a bit more automatic (that's the audience I'm trying to reach with reports. I'm really excited about slidify. I'm working through it more and more and understanding i before incorporating it fully. Thanks for all your assistance.
I understand. One way for you to achieve this is to write a wrapper around author
so that after creating the scaffolding, it copies the custom css files to assets/css
.
Yeah I think this is a very straight forward approach. I am understanding
more how css works (I am reading the head first book on html and css right
now). Very cool stuff (I'm a non programmer who fell in love with R and am
getting to like this programming thing). I planned on using author inside
of two of my functions so adding a file copy to copy the css is easy
(didn't know you could have several css files at the same time).
On Fri, Mar 22, 2013 at 9:57 AM, Ramnath Vaidyanathan <
notifications@github.com> wrote:
I understand. One way for you to achieve this is to write a wrapper around
author so that after creating the scaffolding, it copies the custom css
files to assets/css.—
Reply to this email directly or view it on GitHubhttps://github.com//issues/18#issuecomment-15297807
.