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

[Experimental] Transitions for bespoke template #381

Merged
merged 16 commits into from
Aug 28, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

## [Unreleased]

### Added

- Experimental transitions for bespoke template ([#382](https://github.com/marp-team/marp-cli/issues/382), [#381](https://github.com/marp-team/marp-cli/pull/381))

### Fixed

- Improve an activation behavior from dock in preview mode on macOS ([#380](https://github.com/marp-team/marp-cli/pull/380))

### Changed

- Update Dock icon in preview mode on macOS to suit for macOS Big Sur ([#380](https://github.com/marp-team/marp-cli/pull/380))
- Update Dock icon in preview mode on macOS to suit for Big Sur ([#380](https://github.com/marp-team/marp-cli/pull/380))

## v1.3.2 - 2021-08-18

Expand Down
64 changes: 34 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ The `bespoke` template is using [Bespoke.js](https://github.com/bespokejs/bespok
- **Fragmented list**: Recognize [Marpit's fragmented list](https://github.com/marp-team/marpit/issues/145) and appear list one-by-one if used `*` and `1)` as the bullet marker.
- **Presenter view**: Open presenter view in external window by hitting <kbd>p</kbd> key.
- **Progress bar** (optional): By setting `--bespoke.progress` option, you can add a progress bar on the top of the deck.
- [**Slide transitions** _(EXPERIMENTAL)_][transitions]: You may turn on slide transitions support powered by [Shared Element Transitions API proposal](https://github.com/WICG/shared-element-transitions) by `--bespoke.transition` option. Refer to [marp-team/marp-cli#382][transitions] for details.

[transitions]: https://github.com/marp-team/marp-cli/issues/382

> ℹ️ Presenter view may be disabled if [the browser restricted using localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Feature-detecting_localStorage) (e.g. Open HTML in the old Safari with private browsing, or open the _local_ HTML file with Chrome that has blocked 3rd party cookies in `chrome://settings/content/cookies`).

Expand Down Expand Up @@ -446,36 +449,37 @@ If you want to prevent looking up a configuration file, you can pass `--no-confi

### Options

| Key | Type | CLI option | Description |
| :---------------- | :-------------------------: | :-------------------: | :----------------------------------------------------------------------------------------------------- |
| `allowLocalFiles` | boolean | `--allow-local-files` | Allow to access local files from Markdown while converting PDF _(NOT SECURE)_ |
| `author` | string | `--author` | Define author of the slide deck |
| `bespoke` | object | | Setting options for `bespoke` template |
| ┗ `osc` | boolean | `--bespoke.osc` | \[Bespoke\] Use on-screen controller (`true` by default) |
| ┗ `progress` | boolean | `--bespoke.progress` | \[Bespoke\] Use progress bar (`false` by default) |
| `description` | string | `--description` | Define description of the slide deck |
| `engine` | string \| Class \| Function | `--engine` | Specify Marpit based engine |
| `html` | boolean \| object | `--html` | Enable or disable HTML (Configuration file can pass [the whitelist object] if you are using Marp Core) |
| `image` | `png` \| `jpeg` | `--image` | Convert the first slide page into an image file |
| `images` | `png` \| `jpeg` | `--images` | Convert slide deck into multiple image files |
| `imageScale` | number | `--image-scale` | The scale factor for rendered images (`1` by default, or `2.5` for PPTX conversion) |
| `inputDir` | string | `--input-dir` `-I` | The base directory to find markdown and theme CSS |
| `jpegQuality` | number | `--jpeg-quality` | Setting JPEG image quality (`85` by default) |
| `keywords` | string \| string[] | `--keywords` | Define keywords for the slide deck (Accepts comma-separated string and array of string) |
| `lang` | string | | Define the language of converted HTML |
| `ogImage` | string | `--og-image` | Define [Open Graph] image URL |
| `options` | object | | The base options for the constructor of engine |
| `output` | string | `--output` `-o` | Output file path (or directory when input-dir is passed) |
| `pdf` | boolean | `--pdf` | Convert slide deck into PDF |
| `pdfNotes` | boolean | `--pdf-notes` | Add [presenter notes][marpit presenter notes] to PDF as annotations |
| `preview` | boolean | `--preview` `-p` | Open preview window |
| `server` | boolean | `--server` `-s` | Enable server mode |
| `template` | `bare` \| `bespoke` | `--template` | Choose template (`bespoke` by default) |
| `theme` | string | `--theme` | Override theme by name or CSS file |
| `themeSet` | string \| string[] | `--theme-set` | Path to additional theme CSS files |
| `title` | string | `--title` | Define title of the slide deck |
| `url` | string | `--url` | Define [canonical URL] |
| `watch` | boolean | `--watch` `-w` | Watch input markdowns for changes |
| Key | Type | CLI option | Description |
| :---------------- | :-------------------------: | :--------------------: | :---------------------------------------------------------------------------------------------------------- |
| `allowLocalFiles` | boolean | `--allow-local-files` | Allow to access local files from Markdown while converting PDF _(NOT SECURE)_ |
| `author` | string | `--author` | Define author of the slide deck |
| `bespoke` | object | | Setting options for `bespoke` template |
| ┗ `osc` | boolean | `--bespoke.osc` | \[Bespoke\] Use on-screen controller (`true` by default) |
| ┗ `progress` | boolean | `--bespoke.progress` | \[Bespoke\] Use progress bar (`false` by default) |
| ┗ `transition` | boolean | `--bespoke.transition` | \[Bespoke\] [Enable transitions powered by Shared Element Transitions API][transitions] (EXPERIMENTAL) |
| `description` | string | `--description` | Define description of the slide deck |
| `engine` | string \| Class \| Function | `--engine` | Specify Marpit based engine |
| `html` | boolean \| object | `--html` | Enable or disable HTML tags (Configuration file can pass [the whitelist object] if you are using Marp Core) |
| `image` | `png` \| `jpeg` | `--image` | Convert the first slide page into an image file |
| `images` | `png` \| `jpeg` | `--images` | Convert slide deck into multiple image files |
| `imageScale` | number | `--image-scale` | The scale factor for rendered images (`1` by default, or `2.5` for PPTX conversion) |
| `inputDir` | string | `--input-dir` `-I` | The base directory to find markdown and theme CSS |
| `jpegQuality` | number | `--jpeg-quality` | Setting JPEG image quality (`85` by default) |
| `keywords` | string \| string[] | `--keywords` | Define keywords for the slide deck (Accepts comma-separated string and array of string) |
| `lang` | string | | Define the language of converted HTML |
| `ogImage` | string | `--og-image` | Define [Open Graph] image URL |
| `options` | object | | The base options for the constructor of engine |
| `output` | string | `--output` `-o` | Output file path (or directory when input-dir is passed) |
| `pdf` | boolean | `--pdf` | Convert slide deck into PDF |
| `pdfNotes` | boolean | `--pdf-notes` | Add [presenter notes][marpit presenter notes] to PDF as annotations |
| `preview` | boolean | `--preview` `-p` | Open preview window |
| `server` | boolean | `--server` `-s` | Enable server mode |
| `template` | `bare` \| `bespoke` | `--template` | Choose template (`bespoke` by default) |
| `theme` | string | `--theme` | Override theme by name or CSS file |
| `themeSet` | string \| string[] | `--theme-set` | Path to additional theme CSS files |
| `title` | string | `--title` | Define title of the slide deck |
| `url` | string | `--url` | Define [canonical URL] |
| `watch` | boolean | `--watch` `-w` | Watch input markdowns for changes |

[the whitelist object]: https://github.com/marp-team/marp-core#html-boolean--object

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"@types/cheerio": "^0.22.30",
"@types/express": "^4.17.13",
"@types/jest": "^27.0.1",
"@types/markdown-it": "^12.2.0",
"@types/node": "~14.17.9",
"@types/pug": "^2.0.5",
"@types/supertest": "^2.0.11",
Expand Down
40 changes: 27 additions & 13 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface IMarpCLIArguments {
bespoke?: {
osc?: boolean
progress?: boolean
transition?: boolean
}
configFile?: string | false
description?: string
Expand Down Expand Up @@ -102,14 +103,40 @@ export class MarpCLIConfig {
return undefined
})()

const preview = (() => {
const p = this.args.preview ?? this.conf.preview ?? false

if (p && process.env.IS_DOCKER) {
warn(
`Preview window cannot show in an official docker image. Preview option was ignored.`
)
return false
}

return p
})()

const template = this.args.template || this.conf.template || 'bespoke'
const templateOption: TemplateOption = (() => {
if (template === 'bespoke') {
const bespoke = this.conf.bespoke || {}
const transition = this.args.bespoke?.transition ?? bespoke.transition

if (transition) {
info(
'An EXPERIMENTAL transition support for bespoke template is enabled. ' +
'It is using the shared element transition API proposal and it is not yet stable. ' +
(preview
? ''
: `Recommend to use with ${chalk.yellow`--preview`} option for trying transitions. `) +
`Track the latest information at ${chalk.blueBright`https://github.com/marp-team/marp-cli/issues/382`}.`
)
}

return {
osc: this.args.bespoke?.osc ?? bespoke.osc,
progress: this.args.bespoke?.progress ?? bespoke.progress,
transition,
}
}
return {}
Expand Down Expand Up @@ -187,19 +214,6 @@ export class MarpCLIConfig {
return scale
})()

const preview = (() => {
const p = this.args.preview ?? this.conf.preview ?? false

if (p && process.env.IS_DOCKER) {
warn(
`Preview window cannot show in an official docker image. Preview option was ignored.`
)
return false
}

return p
})()

return {
imageScale,
inputDir,
Expand Down
2 changes: 2 additions & 0 deletions src/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ export class Converter {
: undefined,
renderer: (tplOpts) => {
const engine = this.generateEngine(tplOpts)
tplOpts.modifier?.(engine)

const ret = engine.render(stripBOM(`${markdown}${additionals}`))
const info = engine[engineInfo]

Expand Down
58 changes: 58 additions & 0 deletions src/engine/transition-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Marpit } from '@marp-team/marpit'
import type MarkdownIt from 'markdown-it'

const inverted = {
'reveal-left': 'reveal-right',
'reveal-right': 'reveal-left',
'reveal-up': 'reveal-down',
'reveal-down': 'reveal-up',
'cover-left': 'cover-right',
'cover-right': 'cover-left',
'cover-up': 'cover-down',
'cover-down': 'cover-up',
fade: 'fade',
explode: 'implode',
implode: 'explode',
}

const transitions: Record<string, string> = {
...Object.keys(inverted).reduce<Record<string, string>>(
(acc, transition) => ({ ...acc, [transition]: transition }),
{}
),
reveal: 'reveal-left',
cover: 'cover-left',
}

export default function transitionPlugin(md: MarkdownIt & { marpit: Marpit }) {
md.marpit.customDirectives.local.transition = (value) => {
if (typeof value !== 'string') return {}

const transition = transitions[value]
if (!transition) return { transition: undefined, transitionBack: undefined }

const transitionBack: string | undefined = inverted[transition]
return { transition, ...(transitionBack ? { transitionBack } : {}) }
}

md.core.ruler.after(
'marpit_directives_apply',
'marp_cli_transition',
(state) => {
if (state.inlineMode) return false

for (const token of state.tokens) {
const { marpitDirectives } = token.meta || {}

if (marpitDirectives?.transition) {
token.attrSet(`data-transition`, marpitDirectives.transition)
}
if (marpitDirectives?.transitionBack) {
token.attrSet(`data-transition-back`, marpitDirectives.transitionBack)
}
}

return true
}
)
}
9 changes: 8 additions & 1 deletion src/marp-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ export const marpCli = async (
group: OptionGroup.Template,
type: 'boolean',
},
'bespoke.transition': {
describe:
'[Bespoke] Enable transitions powered by Shared Element Transitions API (EXPERIMENTAL)',
defaultDescription: 'false',
group: OptionGroup.Template,
type: 'boolean',
},
title: {
describe: 'Define title of the slide deck',
group: OptionGroup.Meta,
Expand Down Expand Up @@ -221,7 +228,7 @@ export const marpCli = async (
type: 'string',
},
html: {
describe: 'Enable or disable HTML tag',
describe: 'Enable or disable HTML tags',
group: OptionGroup.Marp,
type: 'boolean',
},
Expand Down
1 change: 1 addition & 0 deletions src/templates/bespoke/bespoke.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ $progressHeight: 5px;
border-radius: 7px;
bottom: 50px;
color: #fff;
contain: paint;
display: block;
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
Expand Down
2 changes: 2 additions & 0 deletions src/templates/bespoke/bespoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import bespokeProgress from './progress'
import bespokeState from './state'
import bespokeSync from './sync'
import bespokeTouch from './touch'
import bespokeTransition from './transition'
import { getViewMode, popQuery, setViewMode, viewModes } from './utils'
import bespokeWakeLock from './wake-lock'

Expand Down Expand Up @@ -52,6 +53,7 @@ export default function bespokeTemplate(
[[x, _, _], bespokeProgress],
[[x, x, _], bespokeTouch()],
[[x, _, _], bespokeOSC()],
[[x, _, _], bespokeTransition],
[[x, x, x], bespokeFragments],
[[x, x, _], bespokeWakeLock]
)
Expand Down
Loading