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

[RFC] Download as PDF #136

Closed
seshrs opened this issue Nov 9, 2021 · 3 comments · Fixed by #225
Closed

[RFC] Download as PDF #136

seshrs opened this issue Nov 9, 2021 · 3 comments · Fixed by #225
Labels
enhancement New feature or request question Further information is requested

Comments

@seshrs
Copy link
Member

seshrs commented Nov 9, 2021

Motivation

One of Primer Spec's features is that print-previews are beautifully-formatted, so students can use their browsers' "Print to PDF" functionality to save copies of a spec for offline access.

However, I think I've seen Piazza questions from students asking the same question. I think many students may not be familiar with their browsers' "Print to PDF" capability, or maybe they assume that the spec won't look good when printed.

Ideally, Primer Spec should show some UI to let students know that they can save specs as a PDF. But how do we do it?

Options I considered

Option 1: Educate students about "Print to PDF"

Pros:

  • "Easiest" to implement

Cons:

  • This is hard to get right. Where would we show this UI in a way that is both useful and discoverable? Also we'd have to write concise instructions for all major browsers, or link to external websites that show students how to do it.
  • In other words, I think this loads too much "unnecessary" cognitive overhead on students who are just looking for a way to download the spec.

Option 2: Generate the PDF from JavaScript

I explored multiple JS --> PDF options over the past few weeks. Click here for details.
  • Browsers don't have a way to let website programmatically generate a PDF (unfortunately 😞).
  • jsPDF produces a nice-looking PDF from HTML, but has bugs related to page margins. Also the text isn't selectable.
  • PDFKit is a bit harder to use, and can only generate PDFs from scratch. Similarly PDFMake on its own is good at generating new PDFs, not converting HTML to PDF. Other libraries have similar constraints.
  • I considered compiling existing libraries like wkhtmltopdf and WeasyPrint to WASM. But all of these libraries have external and OS dependencies to generate PDFs — this makes compiling to WASM hard!

It seems like the most appropriate implementation here is to use PDFMake in conjunction with html-to-pdfmake.

Pros:

  • Text is selectable.
  • Any Primer Spec page will be able to generate a PDF version of the page contents.

Cons:

  • The generated PDF looks plain, and looks very different from the Primer Spec page. Some styling and customization is possible, but it's quite limited.
Example page generate by Option 2

Option 3: GitHub Actions generates PDF using headless Chrome

Click here for details on how it would work.
  • Create a new GitHub Actions workflow. It should run on pushes to the `main` branch of the website repositories. The action performs the following steps:
    • Delete then create a `/pdf` directory.
    • Start Jekyll server with website files.
    • For each HTML file:
      • Query its content, compute a hash: CONTENT_HASH
      • Compute a hash from the relative path: PATH_HASH
      • Use headless Chrome to generate a PDF and store at filepath pdfs/_.pdf
  • In the Primer Spec JS code:
    • Config option needs to be set to opt-in to looking for PDF files.
    • After page loads, use original HTML source to compute CONTENT_HASH. Also compute PATH_HASH.
    • Make HEAD request to pdfs/_.pdf. If the file exists, show a "download" button in the UI.

Pros:

  • PDF quality is equivalent to printing the page. Text is selectable, the pages look beautiful.
  • This basically builds the system needed for Spec change notification #92 to work!

Cons:

  • Each repo that wants to make downloadable PDFs available to students needs to opt-in and add the GitHub action.

Option 4: Create an HTML --> PDF server

Like Prince. But the server could literally use Chrome to render the PDF and return it.

We'd probably need to create a system that prevents spamming the server.

Pros:

  • PDF quality equivalent to option 3.
  • Any Primer Spec repo can use it with a bit of effort.

Cons:

  • Someone needs to pay for the server 😞
  • We have to figure out how to prevent spam/abuse.

My opinion: I like Option 3 (GitHub Actions)

Personally, I prefer Option 3 (GitHub Actions workflow generates PDF). I like it best because of the high-quality PDFs, but I'm not super-happy that course websites need to integrate using GitHub Actions.

Option 2 (generate a bespoke PDF) is also good, but will involve much more work in figuring out how to make a nice-looking PDF. Also, the resulting PDF will never look like a Primer Spec page (but maybe that's a good thing...?)

I don't like Option 1 (UI to educate users) 😆
Option 4 (HTML --> PDF server) involves spam/abuse challenges, and there's a financial cost too.

NOTE: We also need to think about stale PDFs — what if the spec changes after a student has downloaded the PDF? It should be possible for a student to compare their PDF with the contents on a course's website. Essentially, this would be a combination of #92 and including the download-date in the PDF. (This is another reason I like Option 3, it builds the system needed for #92 to work.)

Request for Comments

Comments and suggestions are appreciated! Next week, I'll begin implementing Option 3 if there are no differing opinions.

@seshrs seshrs added the enhancement New feature or request label Nov 9, 2021
@awdeorio
Copy link
Contributor

awdeorio commented Nov 9, 2021

This is a tricky problem.

I'm not super excited about the overhead of adding a GitHub action for Option 3. It will certainly generate Git merge conflicts when multiple branches update the spec. This problem is similar to the starter files tarball problem and most people (including instructors) are helpless when it comes to resolving merge conflicts.

I kinda like Option 1 despite its limitations.

@seshrs
Copy link
Member Author

seshrs commented Oct 22, 2022

Update: I am one step closer to making this a reality! 😃

Now that GitHub Pages can be deployed via GitHub Actions, we can run arbitrary commands to generate static files. I created a custom action to build Primer Spec (see #212).

For the past month, I've been playing around trying to get dynamic PDF generation to work. Thanks to amazing support from GitHub's Support team, I have a working prototype!

Now, all that's left is to figure out how to create a UI in Primer Spec to link students to the PDF. I'll need some time to explore UIs (and maybe correspond with @bellakiminsun) — meanwhile, I'd welcome suggestions and design proposals from anyone 😄

@bellakiminsun
Copy link

bellakiminsun commented Oct 22, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants