-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
feat: PDF handout (slides on top, notes on bottom of page) #1421
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for slidev ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your contribution! I think this feature is quite useful. btw, the commits I pushed earlier contain no actual function-related changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we simplify the handout print logic here? There seems to be some duplicated code. And is that possible to have the cover and the content on a single page, so that we don't need to concat them and recalculate the links manually?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kept the cover and content separate because I use the same cover layout not only for a slide handout but also for a lab guide hand out (which is another PDF but generated from a Nuxt content site).
In general I like the idea of having the content on a single page. Now that you mention it I don't remember why I did it in two steps..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way I generate the lab guide from a nuxt content site and the issue is that the content is not really structured in pages (or slides). Alas a single nuxt content page can stretch over various print pages. So one does not know exactly where to do a page break (which is not a problem with Slides). For this reason I just export all nuxt content articles to a single PDF (the browser automatically does the page breaks) and generate the footer with the page numbers separately using my slidev template. Of course this is very specific and certainly out of scope of Slidev. But I just wanted to mention my reason for implementing it in such a weird way ;)
join(root, 'HandoutBottom.vue'), | ||
] | ||
} | ||
else if (layer === 'handout-cover') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure whether handout-cover
should be a global layer or a layout.
const { isPrintMode } = useNav() | ||
|
||
watchEffect(() => { | ||
const html = document.body.parentNode as HTMLElement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think maybe we don't need a .print
class here. Because when this component is loaded, the page must be in the print mode.
Thanks for having a look at it and cleaning it up. I really appreciate it. I fetched your changes and seems to work. |
|
||
<div class=""> | ||
<HandoutBottom :pageNumber="index + 100" /> | ||
<HandoutBottom :page-number="index + 100" /> | ||
<!-- I would like to do this in HandoutBottom, but somehow props don't get passed. --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove the hard-coded page numbering then
Hello, there is an almost finished PR #1513 which allows users to provide their own print templates. Would that help? |
@KermanX I synced the current pull request with main. Unfortunately, I did not get around yet to implement the changes you mentioned. |
Ok, thanks for the info, I will have a look how to implement it using this PR. |
So I am starting to use this the mentioned PR, works but I have one question and two issue I am stuck with.
|
{ | ||
name: 'cover', | ||
path: '/cover', | ||
component: () => import('../pages/cover/print.vue'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this component be in /handout
without being a route?
.option('cover', { | ||
type: 'boolean', | ||
describe: 'prepend cover to handout, needs handout-cover.vue in project', | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we don't need this option? We could do it automatically when handout-cover.vue
presents.
.option('handout', { | ||
type: 'boolean', | ||
describe: 'Export handout with slides on top and notes on bottom, optionally prepending a cover', | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be --type=handout
(default to slides). So later, we could merge export-notes
to --type=notes
and unify into a single command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pull request introduces a new option for slide export. It allows for the creation of an A4 page with the slide on the top and the speaker notes on the bottom.
The footer of the pages is customizable using a custom component
handout-bottom.vue
, similar toglobal-bottom.vue
for slides.Optionally, it can create cover pages by passing the
--cover
option, which then renders another custom componenthandout-cover.vue
. Both of these components need to be in your theme or project root.I have added some example components to the starter.
Example Usage
The code creates 2 temporary files:
It then prepends the cover and merges slides and handouts. In this way, we can reuse the slide generation code. However, this breaks hyperlinks. Therefore, I have ensured to perform all necessary calculations to make them clickable also in the final PDF.
The final file will be:
handout-slides-export.pdf
Caveat
This feature requires the inclusion of this pull request to work properly: #1419Without it, each click exports a slide, which then desynchronizes the merge with the notes causing errors.
Possible enhancements.
Terminology
Since the term "notes" was already taken, I called the API "handout", but it might be confusing, as /handout is just a helper page to generate the lower part of the final handout and will be merged with the slides to create the final handout.
Fix
pageNumber
paramSomehow the pageNumber param does not get passed to HandoutBottom here: in PrintHandout.vue. This may be due to the way the component is imported. It would be nice to have, because for now, the page numbering is hardcoded in Slidev and not customizable.
Configure output name
Allow configuring the output name of the handout
handout-slides-export.pdf