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

paginate: skip directive #359

Merged
merged 6 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 60 additions & 6 deletions docs/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,39 +181,93 @@ It is useful when you want to create a slide deck from a plain Markdown. Even if

### Pagination

We support a pagination by the `paginate` local directive.
We support pagination by the `paginate` local directive.

```markdown
<!-- paginate: true -->

You would be able to see a page number of slide in the lower right.
```

#### Configuring pagination

There are 2 things happening on each slide:
- the page number is rendered *and*
- the page number is being incremented.

You can control both of these with the `paginate` directive:

| `paginate` | Page number | Increment |
| ---------- | ----------- | --------- |
| `true` | Show | Yes |
| `false` | Hide | Yes |
| `hold` | Show | No |
| `skip` | Hide | No |

#### Skip pagination on title slide

Simply you have to move a definition of `paginate` directive to an inside of a second page.
A common use case is excluding the title slide from pagination.
For this you simply have to define the `paginate` directive on the second page instead of the first.

```markdown
# Title slide

This page will not paginate by lack of `paginate` local directive.
This page will not have pagination by lack of the `paginate` directive.

---

<!-- paginate: true -->

It will paginate slide from a this page.
Pagination will render from this slide onwards (starting at 2).
```

Or also can use the spot directive.
Or you can use the spot directive.

```markdown
---
paginate: true
_paginate: false
_paginate: false # or use `_paginate: skip`
---
```

#### `paginate: skip` and `paginate: hold`

To both exclude a page from pagination and hide the pagination at the same time use `skip`:

```markdown
<!-- _paginate: skip -->
# Slide to exclude

This page will not update the page number and also not show the pagination
```

You can exclude a page from pagination but keep the pagination visible using `hold`:

```markdown
---
paginate: true
---

# Slide 1

- bullet point 1

> Page 1 of 1

---
<!-- _paginate: hold -->

# Slide 2

- bullet point 1
- bullet point 2

> Page 1 of 1
```

This is useful if you want to do "animations" by having multiple similar slides each only changing a little bit while keeping the same page number.
yhatt marked this conversation as resolved.
Show resolved Hide resolved


### Header and footer

When you have to be shown the same content across multiple slides like a title of the slide deck, you may use `header` or `footer` local directives.
Expand Down
25 changes: 23 additions & 2 deletions src/markdown/directives/apply.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ function _apply(md, opts = {}) {
(state) => {
if (state.inlineMode) return

// compute the total number of skipped pages
let totalSkippedSlides = 0
for (const token of state.tokens) {
const { marpitDirectives } = token.meta || {}
if (marpitDirectives && (marpitDirectives.paginate === 'hold' || marpitDirectives.paginate === 'skip')) {
totalSkippedSlides++
}
}

// keep track of slides that were skipped using one of the following
// directives:
// `paginate: skip`, `_paginate: skip`,
// `paginate: hold`, or `_paginate: hold
let currentSkippedSlides = 0

for (const token of state.tokens) {
const { marpitDirectives, marpitSlide, marpitSlideTotal } =
token.meta || {}
Expand Down Expand Up @@ -85,8 +100,14 @@ function _apply(md, opts = {}) {
}

if (marpitDirectives.paginate) {
token.attrSet('data-marpit-pagination', marpitSlide + 1)
token.attrSet('data-marpit-pagination-total', marpitSlideTotal)
if (marpitDirectives.paginate === 'hold' || marpitDirectives.paginate === 'skip') {
currentSkippedSlides++
}

if (marpitDirectives.paginate !== 'skip') {
token.attrSet('data-marpit-pagination', marpitSlide - currentSkippedSlides + 1)
token.attrSet('data-marpit-pagination-total', marpitSlideTotal - totalSkippedSlides)
}
}

if (marpitDirectives.header)
Expand Down
2 changes: 1 addition & 1 deletion src/markdown/directives/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const locals = Object.assign(Object.create(null), {
color: (v) => ({ color: v }),
footer: (v) => (typeof v === 'string' ? { footer: v } : {}),
header: (v) => (typeof v === 'string' ? { header: v } : {}),
paginate: (v) => ({ paginate: (v || '').toLowerCase() === 'true' }),
paginate: (v) => ({ paginate: ['hold', 'skip'].includes(v) ? v : (v || '').toLowerCase() === 'true' }),
})

export default [...Object.keys(globals), ...Object.keys(locals)]
92 changes: 91 additions & 1 deletion test/markdown/directives/apply.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,18 +219,108 @@ describe('Marpit directives apply plugin', () => {

# Slide 1

Pagination is not rendered

---

## Slide 2

Pagination is rendered (2 of 2)
`

const $ = load(mdForTest().render(paginateDirs))
const sections = $('section')

expect(sections.eq(0).data('marpit-pagination')).toBeUndefined()
expect(sections.eq(0).data('marpit-pagination-total')).toBeUndefined()
expect(sections.eq(1).data('marpit-pagination')).toBe(2)
expect(sections.eq(1).data('marpit-pagination-total')).toBe(2)
})
})

describe('Paginate with skipped slides', () => {
it('applies data-marpit-pagination attribute with a _paginate:hold slide', () => {
const paginateDirs = dedent`
---
paginate: true
_paginate:
yhatt marked this conversation as resolved.
Show resolved Hide resolved
---

# Slide 1

- Page is counted (1 of 2)
- Pagination is not rendered

---

<!--
_paginate: hold
-->

## Slide 2

- Page is not counted
- Pagination is rendered (1 of 2)

---

## Slide 3

- Page is counted
- Pagination is rendered (2 of 2)
`

const $ = load(mdForTest().render(paginateDirs))
const sections = $('section')

expect(sections.eq(0).data('marpit-pagination')).toBeUndefined()
expect(sections.eq(0).data('marpit-pagination-total')).toBeUndefined()
expect(sections.eq(1).data('marpit-pagination')).toBeTruthy()
expect(sections.eq(1).data('marpit-pagination')).toBe(1)
expect(sections.eq(1).data('marpit-pagination-total')).toBe(2)
expect(sections.eq(2).data('marpit-pagination')).toBe(2)
expect(sections.eq(2).data('marpit-pagination-total')).toBe(2)
})

it('applies data-marpit-pagination attribute with a _paginate:skip slide', () => {
const paginateDirs = dedent`
---
paginate: true
_paginate:
---

# Slide 1

- Page is counted (1 of 2)
- Pagination is not rendered

---

<!--
_paginate: skip
-->

## Slide 2

- Page is not counted
- Pagination is not rendered (1 of 2)

---

## Slide 3

- Page is counted
- Pagination is rendered (2 of 2)
`

const $ = load(mdForTest().render(paginateDirs))
const sections = $('section')

expect(sections.eq(0).data('marpit-pagination')).toBeUndefined()
expect(sections.eq(0).data('marpit-pagination-total')).toBeUndefined()
expect(sections.eq(1).data('marpit-pagination')).toBeUndefined()
expect(sections.eq(1).data('marpit-pagination-total')).toBeUndefined()
expect(sections.eq(2).data('marpit-pagination')).toBe(2)
expect(sections.eq(2).data('marpit-pagination-total')).toBe(2)
})
})
})
Expand Down