Skip to content

Commit

Permalink
Merge pull request joshed-io#133 from davidovich/improve-plugin-support
Browse files Browse the repository at this point in the history
Improve plugin support
  • Loading branch information
dzello authored Jan 9, 2023
2 parents 5fba253 + 4ad5f5e commit ebe36e2
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 39 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ Then you can do this in a slide:
Displayed equations are wrapped in double-\$
$$\frac{n!}{k!(n-k)!} = \binom{n}{k}$$
$$\frac{n!}{k!(n-k)!} = \binom{n}{k}$$
Inline equations like $E=mc^2$ are wrapped in single-\$
```
Expand Down Expand Up @@ -419,20 +419,36 @@ Customize the Reveal.js presentation by setting these values in `config.toml` or
- `reveal_hugo.reveal_cdn`: The location to load Reveal.js files from; defaults to the `reveal-js` folder in the static directory to support offline development. To load from a CDN instead, set this value to `https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0` or whatever CDN you prefer.
- `reveal_hugo.highlight_cdn`: The location to load highlight.js files from; defaults to to the `highlight-js` folder in the static directory to support offline development. To load from a CDN instead, set this value to `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0` or whatever CDN you prefer.
- `reveal_hugo.load_default_plugins`: If set to true (default), the plugins included by default are loaded. These are markdown, highlight.js, notes and zoom.
- `reveal_hugo.plugins`: An array of additional Reveal.js plugins to load, e.g. `["plugin/gallery/gallery.plugin.js"]`. The appropriate files will need to have been copied into the `static` directory. CDN loading is not supported. See here for a [big list of plugins](https://github.com/hakimel/reveal.js/wiki/Plugins,-Tools-and-Hardware) you can try.
- `reveal_hugo.plugins`: (see below) An array of additional Reveal.js plugins to load. The appropriate files will need to have been copied into the `static` or content directory. See here for a [big list of plugins](https://github.com/hakimel/reveal.js/wiki/Plugins,-Tools-and-Hardware) you can try. The original implementation used to accept an array of javascript files (e.g. `["plugin/gallery/gallery.plugin.js"]`), but now reveal-hugo can fully load plugin javascript and css. To enable this mode, You need to provide an array of plugin definition objects with `name`, `source` and an optional `css`, `verbatim` and `order` fields. Reveal-hugo will try to load the plugins at the path specified by `source`. If `verbatim=true` is used, the path is tried as-is. Otherwise, the path is resolved from the content dir or `static` dir. Finally, the `reveal_cdn` is prepended to the path if no other conditions are satisfied. The `order` field controls the order of javascript loading and will seldomly used. See [plugin-example](https://reveal-hugo.dzello.com/plugin-example/) for a plugin walkthrough.

This is how parameters will look in your `config.toml`:

```TOML
[params.reveal_hugo]
theme = "moon"

# the following supposes that menu is accessible in static dir
[[params.reveal_hugo.plugins]]
# Name the plugin. This should be the same name used to register a reveal-js plugin,
# for example RevealMenu, RevealNotes
name = RevealMenu
source = "menu/menu.js"
css = "menu/menu.css"
# verbatim = true # should the css and source paths be used as-is ?
# order = 6 # control the order in which the plugin should be used.
```

Or in the front matter of an `_index.md` file:

```TOML
[reveal_hugo]
theme = "moon"

[[reveal_hugo.plugins]]
name = "gallery"
source = "plugin/gallery/gallery.plugin.js"
css = "plugin/gallery/gallery.css"

```

Include any other attributes in those sections that you'd like to be fed as arguments to `Reveal.initialize` in **snakecase**, so `slide_number` instead of `slideNumber`. Params are converted from snakecase to camelcase before passing to Reveal.js. This is necessary to maintain the proper case of the parameters.
Expand Down Expand Up @@ -537,7 +553,7 @@ If you need to add something to the HTML layout, you can create partials that li
This is the recommended way to add custom CSS and JavaScript to each presentation.

> 💡 Tip: In Hugo, partials live in the `layouts` folder:
>
>
> For example, if you have HTML that is to be placed before every presentation, this would be the structure:
> ```
> - layouts
Expand Down
34 changes: 19 additions & 15 deletions exampleSite/content/plugin-example/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@ outputs = ["Reveal"]
[reveal_hugo]
theme = "night"
margin = 0.2
plugins = ["plugin/gallery/gallery.plugin.js"]

# Deprecated array form. Css needs to be added in
# a head layout override
# plugins = ["plugin/gallery/gallery.plugin.js"]

# New plugin object form; reveal-hugo
# will load your css for you
[[reveal_hugo.plugins]]
name = "gallery"
source = "plugin/gallery/gallery.plugin.js"
css = "plugin/gallery/gallery.css"

+++

# plugin-example
Expand Down Expand Up @@ -64,20 +75,13 @@ Copy the plugin CSS and JavaScript into the static directory

### 2

Add the JavaScript file path to the `plugins` field in the front matter

---

### 3
Add the JavaScript and (optionally css) file path to the `plugins` field in the front matter

Create a `head.html` partial inside of `layouts/partials/plugin-example/reveal-hugo`
```toml
[[reveal_hugo.plugins]]
source = "plugin/gallery/gallery.plugin.js"
css = "plugin/gallery/gallery.css"
```

---

### 4

In `head.html`, add a stylesheet link tag that loads the plugin CSS

---

## THE END
## THE END

This file was deleted.

10 changes: 8 additions & 2 deletions layouts/_default/baseof.reveal.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
<!doctype html>
<html lang="en">
<head>
{{ partial "layout/head" . }}
{{ partial "layout/theme" . }}
{{ partial "layout/head" . -}}
{{ partial "layout/theme" . -}}
{{ $plugins := partial "internal/plugins" . -}}
{{- range $plugins }}
{{- with .css }}

<link rel="stylesheet" href="{{ . | relURL }}"> {{- end -}}
{{ end -}}
<!-- To insert markup before the closing head tag for all presentations,
create layouts/partials/reveal-hugo/head.html -->
{{- partial "reveal-hugo/head" . -}}
Expand Down
11 changes: 11 additions & 0 deletions layouts/partials/internal/func/cleanParams.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{/* This function is meant to remove reveal-js unrelated initializers (like the
plugins array)
*/}}
{{- $params := dict -}}
{{- range $k, $v := . -}}
{{ if not (in (slice "plugins") $k) }}
{{ $params = merge $params (dict $k $v) }}
{{- end -}}
{{- end -}}

{{ return $params }}
19 changes: 19 additions & 0 deletions layouts/partials/internal/func/normalizePath.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

{{ $plugin_path := "" }}
{{/* try different sources of local plugin paths. They can be in the static dir,
or the current content bundle. Setting the "verbatim" attribute to true overrides
the heuristic.
*/}}

{{ if .verbatim | default false }}
{{/* take this path for face value */}}
{{ $plugin_path = .path }}
{{ else if or (fileExists .path) (fileExists (path.Join "static" .path)) }}
{{/* file exists in content or static, use that */}}
{{ $plugin_path = .path }}
{{ else }}
{{/* file exists on filesystem or in CDN use that */}}
{{ $plugin_path = path.Join .reveal_location .path }}
{{ end }}

{{ return $plugin_path }}
68 changes: 68 additions & 0 deletions layouts/partials/internal/plugins.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{{/* We want to construct a plugins slice of unique plugins. We start by taking the
default plugins if they are enabled, then iterate on additional user defined
plugins.

We support the legacy style of plugin paths (although this might break in reveal-js
>= 4.0 - we might revisit this.)
*/}}

{{/* Use a scratch dict to ensure unicity of plugins. This dict has an order key
because the plugins need to be loaded in a specific order (i.e. markdown
depends on marked)
*/}}
{{ $startOrder := 0}}
{{ $plugins := newScratch }}
{{ if $.Param "reveal_hugo.load_default_plugins" | default true }}
{{ $plugins.SetInMap "plugins" "marked" (dict "order" 0 "source" "plugin/markdown/marked.js") }}
{{ $plugins.SetInMap "plugins" "RevealMarkdown" (dict "order" 1 "source" "plugin/markdown/markdown.js") }}
{{ $plugins.SetInMap "plugins" "RevealHighlight" (dict "order" 2 "source" "plugin/highlight/highlight.js") }}
{{ $plugins.SetInMap "plugins" "zoom" (dict "order" 3 "source" "plugin/zoom-js/zoom.js") }}

<!-- always use local version of the notes plugin since HTML file it requires isn't on CDN -->
{{ $plugins.SetInMap "plugins" "RevealNotes" (dict "order" 4 "source" "reveal-js/plugin/notes/notes.js"
"verbatim" true) }}
{{ $startOrder = 5 }}
{{ end }}

{{ $allPlugins := $.Site.Param "reveal_hugo.plugins" | default slice }}
{{ $allPlugins = append $allPlugins ($.Page.Param "reveal_hugo.plugins" | default slice ) }}

{{/* load custom user plugins */}}
{{ range $allPlugins }}
{{ if reflect.IsMap . }}
{{/* we already have a plugin definition object */}}
{{ with .order }}
{{ $startOrder = . }}
{{ end }}
{{ $plugins.SetInMap "plugins" (print .name) (merge . (dict "order" $startOrder) )}}
{{ else if reflect.IsSlice . }}
{{ range . }}
{{/* convert from old plugin path to new plugin object format */}}
{{ $plugins.SetInMap "plugins" (path.BaseName .) (dict "source" . "order" $startOrder) }}
{{ end }}
{{ else }}
{{ $plugins.SetInMap "plugins" (path.BaseName .) (dict "source" . "order" $startOrder) }}
{{ end }}

{{ $startOrder = add $startOrder 1 }}
{{ end }}

{{ $revealLoc := dict "reveal_location" ($.Param "reveal_hugo.reveal_cdn" | default "reveal-js") }}
{{ $normalizedPlugins := slice }}

{{ range $name, $plugin := (sort ($plugins.Get "plugins") "order") }}
{{ $normalizedPlugin := (dict "name" $name) }}

{{ with $plugin.css }}
{{ $normalizedCssPath := partial "internal/func/normalizePath" (merge $plugin (dict "path" . ) $revealLoc ) }}
{{ $normalizedPlugin = merge $plugin (dict "css" $normalizedCssPath)}}
{{ end }}
{{ with $plugin.source }}
{{ $normalizedSourcePath := partial "internal/func/normalizePath" (merge $plugin (dict "path" . ) $revealLoc ) }}
{{ $normalizedPlugin = merge $plugin (dict "source" $normalizedSourcePath)}}
{{ end }}

{{ $normalizedPlugins = $normalizedPlugins | append $normalizedPlugin }}
{{ end}}

{{ return $normalizedPlugins }}
27 changes: 9 additions & 18 deletions layouts/partials/layout/javascript.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
link.href = printLocationElement.href + (window.location.search.match(/print-pdf/gi) ? 'pdf.css' : 'paper.css');
document.getElementsByTagName('head')[0].appendChild(link);
</script>
<!-- output Hugo parameters into JavaScript to be used when initializing Reveal.js -->
<script type="application/json" id="reveal-hugo-site-params">{{ jsonify .Site.Params.reveal_hugo | safeJS }}</script>
<script type="application/json" id="reveal-hugo-page-params">{{ jsonify .Page.Params.reveal_hugo | safeJS }}</script>

<!-- load Reveal.js javascripts -->
<script src="{{ printf "%s/js/reveal.js" $reveal_location | relURL }}"></script>
<!-- load Reveal.js plugins -->
Expand All @@ -35,28 +33,21 @@
}
// pattern inspired by https://github.com/RealOrangeOne/hugo-theme-revealjs
var revealHugoDefaults = { center: true, controls: true, history: true, progress: true, transition: "slide" };
var revealHugoSiteParams = JSON.parse(document.getElementById('reveal-hugo-site-params').innerHTML);
var revealHugoPageParams = JSON.parse(document.getElementById('reveal-hugo-page-params').innerHTML);
var revealHugoSiteParams = {{ jsonify (partial "internal/func/cleanParams" .Site.Params.reveal_hugo) | safeJS }};
var revealHugoPageParams = {{ jsonify (partial "internal/func/cleanParams" .Page.Params.reveal_hugo) | safeJS }};

// See all options - https://github.com/hakimel/reveal.js#configuration
var options = Object.assign({},
camelize(revealHugoDefaults),
camelize(revealHugoSiteParams),
camelize(revealHugoPageParams));
Reveal.initialize(options);
</script>
<!-- load Reveal.js plugins after Reveal.js is initialized -->
{{ if $.Param "reveal_hugo.load_default_plugins" | default true }}
{{ $default_plugins := slice "plugin/markdown/marked.js" "plugin/markdown/markdown.js" "plugin/highlight/highlight.js" "plugin/zoom-js/zoom.js" }}
{{ range $default_plugins }}
<script type="text/javascript" src="{{ printf "%s/%s" $reveal_location . | relURL }}"></script>
{{ end }}
<!-- always use local version of the notes plugin since HTML file it requires isn't on CDN -->
<script type="text/javascript" src="{{ "reveal-js/plugin/notes/notes.js" | relURL }}"></script>
{{ end }}
<!-- load custom plugins locally only (not CDN since many plugins won't exist there) -->
{{ range $.Param "reveal_hugo.plugins" }}
<script type="text/javascript" src="{{ . | relURL }}"></script>
{{ end }}

{{- $plugins := partial "internal/plugins" . -}}
{{- range $plugins }}
<script type="text/javascript" src="{{ .source | relURL }}"></script>
{{- end -}}

{{/* check if we need to load mermaid and its render trick.
mermaid is not rendered correctly in reveal if we don't hook
Expand Down

0 comments on commit ebe36e2

Please sign in to comment.