Revealjs Plugins
Overview
Revealjs plugins enable you to extend the capabilities of HTML presentations created with Revealjs. The Reveal Plugin API is very rich, and many of the built-in capabilities of Quarto Revealjs presentations are implemented as plugins, including Menu, Chalkboard, and PDF Export.
Here are some examples of Revealjs plugins packaged as Quarto extensions:
Extension | Description |
---|---|
Pointer | Adds support for switching the cursor to a ‘pointer’ style element while presenting. |
Attribution | Display attribution text along the right edge of slides. |
Quick Start
Here we’ll describe how to create a simple Revealjs plugin extension. We’ll use the quarto create
command to do this. If you are using VS Code or RStudio you should execute quarto create
within their repsective integrated Terminal panes.
To get started, execute quarto create extension revealjs-plugin
within the parent directory where you’d like the plugin extension to be created:
Terminal
$ quarto create extension revealjs-plugin
? Extension Name › shuffler
As shown above, you’ll be prompted for an extension name. Type shuffler
and press Enter—the Revealjs plugin extension is then created:
Creating extension at /Users/jjallaire/quarto/dev/shuffler:
- Created README.md
- Created _extensions/shuffler/_extension.yml
- Created _extensions/shuffler/shuffler.css
- Created _extensions/shuffler/shuffler.js
- Created .gitignore
- Created example.qmd
If you are running within VS Code or RStudio a new window will open with the extension project.
Here’s what the contents of the files in _extensions/shuffler/
look like:
_extensions/shuffler/_extension.yml
title: Shuffler
author: J.J. Allaire
version: 1.0.0
quarto-required: ">=1.2.222"
contributes:
revealjs-plugins:
- name: RevealShuffler
script:
- shuffler.js
stylesheet:
- shuffler.css
_extensions/shuffler/shuffler.js
window.RevealShuffler = function () {
return {
id: "RevealShuffler",
init: function (deck) {
// TODO: Implement your plugin functionality
// Learn more at https://revealjs.com/creating-plugins/
// This example shuffles the deck when the 'T' key is pressed
deck.addKeyBinding({ keyCode: 84, key: "T" }, () => {
deck.shuffle();
});
},
};
};
There is also a shuffler.css
file for providing any styles required by your plugin.
Finally, the example.qmd
file includes code that exercises the extension. For example:
example.qmd
---
title: "Shuffler Example"
format:
revealjs: default
revealjs-plugins:
- shuffler
---
## Breakfast
- Eat eggs
- Drink coffee
## Dinner
- Eat spaghetti
- Drink wine
To develop your plugin, render/preview example.qmd
, and then make changes to shuffler.js
and shuffler.css
(the preview will automatically refresh when you change these files).
Installation and Use
If your extension source code it located within a GitHub repository, then it can be added by referencing the GitHub organization and repository name. For example, you can install the attribution
extension with the following:
Terminal
quarto add quarto-ext/attribution
Note that it is possible to bundle and distribute extensions as simple gzip archives (as opposed to using a GitHub repository as described above). See the article on Distributing Extensions for additional details.
Once an extension has been added, you can use the Reveal plugin by adding it to the reveal-plugins
key. For example:
---
title: "My Presentation"
format: revealjs
revealjs-plugins:
- attribution
---
Plugin Packaging
Note that the plugins listed above were not initially developed for use with Quarto. Rather, they were developed intially as native Revealjs plugins and then packaged as Quarto extensions.
For example, you can find the original implementation of the attribution plugin here: https://github.com/rschmehl/reveal-plugins/tree/main/attribution. The plugin is implemented with a JavaScript file and a CSS file. To make the plugin available as a Quarto extension, we package these files along with an _extension.yml
config file that registers the plugin. Here are the files in the Quarto extension:
LICENSE
README.md
example.qmd
_extensions/
attribution/
_extension.yml
attribution.js
attribution.css
Note that the LICENSE
and README.md
are standard documentation files and the example.qmd
is used for development and documentation of the extension. None of those files are actually installed by end users (rather only the contents of the _extensions
directory is installed).
You can see the full source code of the Quarto version here: https://github.com/quarto-ext/attribution (we’ll also walk through the code in detail below).
Plugin Development
You can develop either entirely new Revealjs plugins from scratch or you can package existing Revealjs extensions as described above.
Here is a list of existing 3rd party plugins for Revealjs that you might consider packaging as Quarto extensions: https://github.com/hakimel/reveal.js/wiki/Plugins,-Tools-and-Hardware.
If you want to develop new plugins, check out the Quarto Reveal extensions listed above as well as the code of other 3rd party Reveal Plugins. The following documentation on the Revealjs website provides additional important technical details:
Plugin Configuration
Some Revealjs plugins make available various user options. If you are developing a plugin from scratch, you should use a distinct key for your plugin’s configuration. Users can use this key alongside other revealjs
options. For example the pointer
extension can be configured as follows:
---
title: "Example Presentation"
format:
revealjs:
pointer:
pointerSize: 18
color: '#32cd32'
revealjs-plugins:
- pointer
---
The extension accesses options using the deck.getConfig()
function:
return {
id: "pointer",
init: (deck) => {
const config = deck.getConfig();
const options = config.pointer || {};
// etc
} }
Note that when packaging an existing Revealjs plugin, you can override its default configuration using the config
key within your _extension.yml
file. For example, these are the overrides provided by the pointer
extension:
title: Pointer
author: Charles Teague
contributes:
revealjs-plugins:
- name: RevealPointer
script:
- pointer.js
stylesheet:
- pointer.css
config:
pointer:
key: "q"
color: "red"
pointerSize: 16
alwaysVisible: false
Example: Attribution
Here we’ll walk through the complete source code for the attribution extension. This extension enables you to display attribution text sideways along the right edge of Revealjs slides.
Here are source files used to develop the extension:
LICENSE
README.md
example.qmd
_extensions/
attribution/
_extension.yml
attribution.js
attribution.css
The example.qmd
and documentation files are used for development of the the extension only (it is not installed by end users). The other files provide extension registration (_extension.yml
) and the actual implementation of the Revealjs plugin (attribution.js
and attribution.css
).
The example.qmd
is a simple one-slide presentation that includes an image along with a a div with class .attribution
:
example.qmd
---
title: "Attribution Extension"
format: revealjs
revealjs-plugins:
- attribution
---
## Forest Image
![](ingtotheforest.jpg)
::: {.attribution)[@ingtotheforest](https://unsplash.com/@ingtotheforest)
Photo courtesy of :::
Note that the revealjs-plugins
key references the attribution
extension, which will implemented in the _extensions/attribution
directory.
The _extension.yml
file indicates that the extension is making available a Revealjs plugin along with the plugin name, script, and style-sheets (note that the plugin name is not arbitrary, it will be whatever name is used within the script that implements the plugin, in this case RevealAttribution
):
_extensions/attribution/_extension.yml
title: Attribution
author: Roland Schmehl
version: 0.1.0
quarto-required: ">=1.2.0"
contributes:
revealjs-plugins:
- name: RevealAttribution
script:
- attribution.js
stylesheet:
- attribution.css
The attribution.js
file contains the implementation of the Plugin using the Revealjs Plugin API:
_extensions/attribution/attribution.js
window.RevealAttribution = window.RevealAttribution || {
id: 'RevealAttribution',
init: function(deck) {
initAttribution(deck);
};
}
const initAttribution = function(Reveal){
var ready = false;
var resize = false;
var scale = 1;
window.addEventListener( 'ready', function( event ) {
var content;
// Remove configured margin of the presentation
var attribution = document.getElementsByClassName("attribution");
var width = window.innerWidth;
var configuredWidth = Reveal.getConfig().width;
var configuredHeight = Reveal.getConfig().height;
= 1/(1-Reveal.getConfig().margin);
scale
for (var i = 0; i < attribution.length; i++) {
= attribution[i].innerHTML;
content .style.width = configuredWidth + "px";
attribution[i].style.height = configuredHeight + "px";
attribution[i].innerHTML = "<span class='content'>" + content + "</span>";
attribution[i].style.transform = 'translate( -50%, -50% ) scale( ' + scale*100 + '% ) rotate(-180deg)';
attribution[i]
}
// Scale with cover class to mimic backgroundSize cover
resizeCover();
;
})
window.addEventListener( 'resize', resizeCover );
function resizeCover() {
// Scale to mimic backgroundSize cover
var attribution = document.getElementsByClassName("attribution");
var xScale = window.innerWidth / Reveal.getConfig().width;
var yScale = window.innerHeight / Reveal.getConfig().height;
var s = 1;
if (xScale > yScale) {
// The div fits perfectly in x axis, stretched in y
= xScale/yScale;
s
}for (var i = 0; i < attribution.length; i++) {
.style.transform = 'translate( -50%, -50% ) scale( ' + s*scale*100 + '% ) rotate(-180deg)';
attribution[i]
}
}
; }
Finally, attribution.css
includes the CSS that repositions and rotates the element with class .attribution
on the far right side of the slide:
_extensions/attribution/attribution.css
/* Attribution plugin: text along the right edge of the viewport */
.attribution{
position: absolute;
top: 50%;
bottom: auto;
left: 50%;
right: auto;
font-size: 0.4em;
pointer-events: none;
text-align: center;
writing-mode: vertical-lr;
transform: translate( -50%, -50% ) scale( 100% ) rotate(-180deg);
}
/* Attribution plugin: activate pointer events for attribution text only */
.attribution .content{
pointer-events: auto;
}