trinker / reports

An R package to assist in the workflow of writing academic articles and other reports
http://cran.us.r-project.org/web/packages/reports/
102 stars 25 forks source link

incorporate reports with slidify #18

Closed trinker closed 11 years ago

trinker commented 11 years ago

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.

jamiefolson commented 11 years ago

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.

trinker commented 11 years ago

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/trinker/reports/issues/18#issuecomment-15038697 .

ramnathv commented 11 years ago

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.

trinker commented 11 years ago

Note to self: Remember to address this: https://github.com/ramnathv/slidify/issues/178#issuecomment-15037427

trinker commented 11 years ago

@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?

ramnathv commented 11 years ago
  1. Yes, the addition will be permanent, once I convince myself that the API to do this is simple and robust.
  2. Yes. Slidify automatically adds any CSS files it finds in assets/css. In order to keep slidifyLibraries 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 file reveal-reports-custom.js and add it to PRESENTATION/assets/css, after you author 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.

jamiefolson commented 11 years ago

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.

ramnathv commented 11 years ago

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.

ramnathv commented 11 years ago

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.

jamiefolson commented 11 years ago

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.

ramnathv commented 11 years ago

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.

ramnathv commented 11 years ago

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>
jamiefolson commented 11 years ago

Whoa. That is neat.

jamiefolson commented 11 years ago

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.

  1. The way you use blocks to allow custom formatting for a section without departing from markdown is really smart.
  2. slide.image.html is nice!
  3. 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 stacks 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.

ramnathv commented 11 years ago

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.

ramnathv commented 11 years ago

Let us continue this discussion on the issues page for Slidify.

jamiefolson commented 11 years ago

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/trinker/reports/issues/18#issuecomment-15098366 .

ramnathv commented 11 years ago

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
ramnathv commented 11 years ago

@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.

trinker commented 11 years ago

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.

ramnathv commented 11 years ago

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.

trinker commented 11 years ago

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.

ramnathv commented 11 years ago

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.

trinker commented 11 years ago

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.

ramnathv commented 11 years ago

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.

trinker commented 11 years ago

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/trinker/reports/issues/18#issuecomment-15297807 .