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

feat: print templates, slide layers and rewrite export function #1513

Closed
wants to merge 27 commits into from

Conversation

KermanX
Copy link
Member

@KermanX KermanX commented Apr 10, 2024

close #1509

This PR:

  • Allow user to customize print template via the --template or -t option. In dev mode, the option is called --print-template.
    • User can add or override print template via ./pages/print/*.{vue,ts}
    • Print page is no longer being bundled in the build mode
    • The export-notes sub-command is removed. Use -t notes instead.
    • Previously, -t was the alias of --theme, but --theme is quite uncommon.
  • Add the "handout" print template (close feat: PDF handout (slides on top, notes on bottom of page) #1421)
  • Add new layers for each slide:
    • layouts/slide-top.vue
    • layouts/slide-bottom.vue
  • Refactors DOM structure

The locations of the files and option names need some discussion.

Copy link

netlify bot commented Apr 10, 2024

Deploy Preview for slidev ready!

Name Link
🔨 Latest commit 75f0744
🔍 Latest deploy log https://app.netlify.com/sites/slidev/deploys/663b2d0a1f118000082ba891
😎 Deploy Preview https://deploy-preview-1513--slidev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@KermanX KermanX mentioned this pull request Apr 11, 2024
@KermanX KermanX mentioned this pull request Apr 14, 2024
@KermanX KermanX marked this pull request as ready for review April 17, 2024 12:11
@KermanX KermanX marked this pull request as draft April 17, 2024 12:14
@KermanX KermanX marked this pull request as ready for review April 17, 2024 12:28
@@ -202,7 +203,8 @@ Options:
- `--range` (`string`): page ranges to export (example: `'1,4-5,6'`).
- `--dark` (`boolean`, default: `false`): export as dark theme.
- `--with-clicks`, `-c` (`boolean`, default: `false`): export pages for every click animation (see https://sli.dev/guide/animations.html#click-animations).
- `--theme`, `-t` (`string`): override theme.
- `--theme` (`string`): override theme.
- `--template`, `-t` (`string`, default: `default`): specify [the print template](/guide/exporting#print-template).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer --type with hard-coded options like slides notes handout - and let ppl to override them instead of creating arbitrary options. Because we might want to do some special handling for each type - over-generalize it might not be ideal for long term.

Copy link
Member Author

@KermanX KermanX Apr 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is OK to allow users to create new print templates. This is because it will be the user/addon's responsibility to handle other options like --with-clicks or so. Otherwise, users are forced to override one of the 3 templates even if there is no connection between the default one and the overridden one.

About the name of this option, should we change all "print templates" into "print types" or only the CLI flag?

@oripka
Copy link
Contributor

oripka commented Apr 17, 2024

In order to make the handout #1421 pull request work with this code I found that I need to be able to control the scaling factor (zoom) inside SlideWrapper.vue

Currently it is retrieved from the front matter

const zoom = computed(() => props.route.meta?.slide?.frontmatter.zoom ?? 1)

If that would be configurable from a template (e.g. via inject) it would solve the problem that I ran into when implementing a notes template (point 2) where one adjusts the width and height correctly to fit an A4 page but the scale of the content is not adjusted and the content overflows out of the slide.

Here is a current draft of the notes template

@KermanX KermanX changed the title feat: custom page templates feat: print template and slide layers Apr 18, 2024
@KermanX
Copy link
Member Author

KermanX commented Apr 18, 2024

In order to make the handout #1421 pull request work with this code I found that I need to be able to control the scaling factor (zoom) inside SlideWrapper.vue

Currently it is retrieved from the front matter

const zoom = computed(() => props.route.meta?.slide?.frontmatter.zoom ?? 1)

If that would be configurable from a template (e.g. via inject) it would solve the problem that I ran into when implementing a notes template (point 2) where one adjusts the width and height correctly to fit an A4 page but the scale of the content is not adjusted and the content overflows out of the slide.

Here is a current draft of the notes template

About the debugging issue you said in #1421, there is a --print-template option in this PR now.

About the slide scale, we can use <SlideContainer> here (I will do this change).

@oripka
Copy link
Contributor

oripka commented Apr 18, 2024

I tried the latest commit. Seems like solving a lot of issues.

One thing I noted is that the page aligns well in Firefox but not in Chrome and when exporting on the command line.

Here is firefox on the left, chrome on the right

image

And a document npx slidev export -t handout

slides-export-handout.pdf

Maybe an issue with some css?

@oripka
Copy link
Contributor

oripka commented Apr 18, 2024

After a bit more testing, it seems that having a slide like this with transitions and renderwhen results in an empty slide.


---


# Test

<RenderWhen context="visible">
    <transition appear name="outro">
<img class="h-80 mx-auto" src="https://github.com/slidevjs/themes/blob/main/screenshots/theme-seriph/01.png?raw=true" alt="">
    </transition>
</RenderWhen>
<!--Test-->

<style>
.outro-enter-from {
  opacity: 0;
  transform: translate(-40px, 40px);
}
.outro-enter-active {
  transition: all 0.5s ease-in-out;
}
.outro-enter-to {
  transform: translate(0, 0);
}
.slidev-layout.outro {
  @apply bg-bottom bg-right;
}

</style>
image

Co-authored-by: Oliver-Tobias Ripka <[email protected]>
@KermanX
Copy link
Member Author

KermanX commented Apr 19, 2024

I spent 2 hours on this, trying to figure out why the page is (exactly) 1.5x larger than the expected size, but made no progress. The output is still like this:

image

@oripka
Copy link
Contributor

oripka commented Apr 19, 2024

I spent 2 hours on this, trying to figure out why the page is (exactly) 1.5x larger than the expected size, but made no progress. The output is still like this:

Yes I have also spend some time debugging. I have found that changing the scale factor to 1.5 in export.ts works with your handout code, when exporting:

  async function genPagePdfOnePiece() {
    await go('print')
    await page.pdf({
      path: output,
      scale: 1.5,
      margin: {
        left: 0,
        top: 0,
        right: 0,
        bottom: 0,
      },
      printBackground: true,
      preferCSSPageSize: true,
    })

It might have to do with the DPI setting when exporting PDFs, here is a gist for debugging that tries to calculate the width and height according to the DPI (which is hardcoded for now): https://gist.github.com/oripka/36f4589df0fa72ed5758261c0a870264

The page breaks are now correct. The notes need a max-w-full in order to take the whole width.

@KermanX
Copy link
Member Author

KermanX commented Apr 19, 2024

t might have to do with the DPI setting when exporting PDFs

I tried to set this setting to 100% and restart the browser:

image

, but the page is still 1.5x larger. I am worried that if we hard-code 1.5 in the code, it may not work on some machine🥺

@oripka
Copy link
Contributor

oripka commented Apr 19, 2024

Maybe this is related to these known issues (pupeteer and chrome):

https://issues.chromium.org/issues/40144973#comment9
puppeteer/puppeteer#666
puppeteer/puppeteer#2278

I tried this code to determine it dynamically, but I think this is the incorrect DPI for printing, as this is one just displaying the page, not while generating the PDF. In my case it is 96. In the docs I found that the default reference value for PDF should be 72, which does not result in the 1.5 scale. It also contradicts the DPI of 144 that I found using tinkering: https://gist.github.com/oripka/36f4589df0fa72ed5758261c0a870264

    const dpi = await page.evaluate(() => {
      const div = document.createElement('div');
      div.style.position = 'absolute';
      div.style.top = 0;
      div.style.left = 0;
      div.style.width = '1in';
      div.style.height = '1in';
      document.body.appendChild(div);
      const height = div.offsetHeight;
      div.remove();
      return height;
    });

Maybe we should provide a sane default, test on Windows, Linux and macOS, in case there are any differences and make it a command line option.

@KermanX KermanX marked this pull request as draft April 19, 2024 13:41
@KermanX
Copy link
Member Author

KermanX commented Apr 19, 2024

After some consideration I think I have to rewrite the export logic (this existing one is kind of messed up) Especially I am going to rewrite the --per-slide option.

@KermanX KermanX changed the title feat: print template and slide layers feat: print templates, slide layers and rewrite export function Apr 19, 2024
@KermanX KermanX added help wanted Extra attention is needed and removed help wanted Extra attention is needed labels Apr 20, 2024
@KermanX KermanX mentioned this pull request Apr 24, 2024
@KermanX KermanX mentioned this pull request May 31, 2024
@KermanX KermanX closed this Jun 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RFC: Custom UI layouts
3 participants