Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

using decktape or pagedown::chrome_page with panelset #67

Closed
yonicd opened this issue Oct 22, 2020 · 13 comments
Closed

using decktape or pagedown::chrome_page with panelset #67

yonicd opened this issue Oct 22, 2020 · 13 comments

Comments

@yonicd
Copy link

yonicd commented Oct 22, 2020

Any ideas how to get decktape.js or chrome_page to convert a slide deck with panelsets to a pdf that can toggle through the panel sets as new pages in the pdf?

The main problem is that the slides get toggled through with a --key=ArrowRight instead of ArrowDown when using the generic command.

When I use react command it doesnt toggle through the slides with a key press but it counts the slides up front, as does chrome_page.

@gadenbuie
Copy link
Owner

Panelsets definitely don't print nicely. It's a little complicated since the panels only exist within one slide, whereas slide continuations are technically completely separate slides.

I have some vague ideas about how I might be able to create a "print mode" for the panelsets and I'm tracking progress to that end in #45.

@yonicd
Copy link
Author

yonicd commented Oct 22, 2020

Not sure why tapedeck generic screws up fonts, it is actually moving through the panelset correctly

@gadenbuie
Copy link
Owner

Oh yeah, I don't use decktape often so I missed the fact that it can move through slides using a keypress action. Panelset modifies the typical remarkjs behavior and listens to ArrowRight events to move through panels, whereas ArrowDown will move through slides. Sounds like decktape could be very useful!

@cderv
Copy link

cderv commented Oct 23, 2020

I don't think this is an issue with the printing tool. In case of chrome, as I said in rstudio/pagedown#192 (comment), it just uses the Pages.printToPDF method of Chrome. I don't think it "navigates" the slide.

However, I think there are some special CSS rules for printed output like @media print (https://developer.mozilla.org/en-US/docs/Web/CSS/@media). I don't know if this is possible, but maybe something can be done to have some CSS that would position nicely the output of panelset. Maybe this requires some JS to... (https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeprint)

Anyway just some ideas I throw here just like that 😄

@gadenbuie
Copy link
Owner

gadenbuie commented Oct 23, 2020

I'm not sure if pagedown's chrome_print() would be the best place to start, but after thinking about this for a bit I wonder if we could use pagedown or chromote to recreate the method used by decktape.js.

In essence, rather than printing using the print CSS media, we'd keep screen emulation and print each slide, navigating between slides by sending an ArrowRight keypress event. Then, depending on implementation, we'd staple the PDFs together into the final PDF of all of the slides.

@cderv
Copy link

cderv commented Oct 23, 2020

I wonder if we could use pagedown or chromote to recreate the method used by decktape.js.

It would be crrri (on github only) or chromote. Not pagedown IMO. it is not made for that compare to the other packages.

And yes, I think that would be possible. You can control the browser with those packages.

@yonicd
Copy link
Author

yonicd commented Oct 23, 2020

@gadenbuie wouldnt it be ArrowRight?

@yonicd
Copy link
Author

yonicd commented Oct 23, 2020

@cderv i got the basics down of navigating, but how do i collect each page to make it into a pdf? i guess i can save each page screenshot as a png or something and then convert to pdf /shrug

Also how do i know how many right arrow hits to move and how do i run the script on a loop through them?

# Helpers -----------------------------------------------------------------

# Press the 'Enter' key
press_enter_key <- function(client) {
  dispatch_enter_key_event <- function(client, type) {
    client$Input$dispatchKeyEvent(
      type = type, 
      windowsVirtualKeyCode = 13, 
      code = "Enter", 
      key = "Enter", 
      text = "\r", 
      unmodifiedText = "\r"
    )
  }
  
  promises::then(
    dispatch_enter_key_event(client, "keyDown"),
    ~ dispatch_enter_key_event(client, "keyUp")
  )
}

press_rightarrow_key <- function(client) {
  dispatch_enter_key_event <- function(client, type) {
    client$Input$dispatchKeyEvent(
      type = type, 
      windowsVirtualKeyCode = 39, 
      code = "ArrowRight", 
      key = "ArrowRight", 
      text = "", 
      unmodifiedText = ""
    )
  }
  
  promises::then(
    dispatch_enter_key_event(client, "keyDown"),
    ~ dispatch_enter_key_event(client, "keyUp")
  )
}

press_downarrow_key <- function(client) {
  dispatch_enter_key_event <- function(client, type) {
    client$Input$dispatchKeyEvent(
      type = type, 
      windowsVirtualKeyCode = 40, 
      code = "ArrowDown", 
      key = "ArrowDown", 
      text = "", 
      unmodifiedText = ""
    )
  }
  
  promises::then(
    dispatch_enter_key_event(client, "keyDown"),
    ~ dispatch_enter_key_event(client, "keyUp")
  )
}

# Main script -------------------------------------------------------------
library(crrri)
url <- 'https://pkg.garrickadenbuie.com/xaringanExtra/panelset'
chrome <- Chrome$new(bin = find_chrome_binary())

client <- chrome$connect(callback = function(client) {
  client$inspect()
})

Page <- client$Page
Input <- client$Input

Page$enable() %...>% {
  Page$navigate(url = url)
  Page$loadEventFired() # await the load event
} %...>% {
  press_rightarrow_key(client)
} %...>% {
  press_downarrow_key(client)
}

chrome$close()

@gadenbuie
Copy link
Owner

I also fiddled with this a bit and have a good process in place, but unfortunately it requires taking screenshots rather than printing to PDF.

The primary issue is that remarkjs includes CSS @media print rules that need to be ignored. I've explored two paths without success:

  1. Trying to get the Page.printToPDF method to ignore the print media rules.

  2. Using JavaScript to delete the @media print rules. This doesn't work because of Chrome's cross-site origin policy that won't let JavaScript modify CSS from other domains. I've tried launching chrome with --disable-web-security but that also didn't work.

Both of the above are techniques used by decktape.js via puppeteer. Maybe the API is different? It's possible that decktape.js bundles an older version of headless chrome to avoid the same origin policy problem. 🤷‍♂️

If you have any advice, @cderv or @yonicd, I'd appreciate it!

@gadenbuie
Copy link
Owner

It took me a while to work out the final details, but I've come up a with a solution that uses headless chrome's print method to print each slide to PDF (and then staple them together with pdftools). https://www.garrickadenbuie.com/blog/print-xaringan-chromote/

@cderv
Copy link

cderv commented Jan 25, 2021

Nice ! Well done!

chromote or crrri are not on CRAN so hard to have this function live in a CRAN package.

But we could do the same trick as in pagedown and use neither to put it inside xaringan maybe ?
it is just a pain to maintain without using any of this package.

So the function living in a file to source is also a nice idea.

@gadenbuie
Copy link
Owner

Thanks @cderv! I also don't feel a ton of pressure to incorporate this into a package because I think most users who use mostly the standard set of xaringan features will be fine using decktape or pagedown::chrome_print().

@yonicd
Copy link
Author

yonicd commented Jan 25, 2021

most users :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants