@farberg/reveal-template 1.1.18 → 1.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/init-reveal.js CHANGED
@@ -11,47 +11,75 @@ import DirTreePlugin from './plugins/reveal-plugin-dir-tree.js';
11
11
  import PrefixUrlPlugin from './plugins/reveal-plugin-prefix-with-base-url.js';
12
12
  import AsciinemaPlugin from './plugins/reveal-plugin-asciinema.js';
13
13
 
14
- const defaultOptions = {
15
- revealOptions: {},
16
- revealPath: "../../reveal.js/",
17
- jsPrefixPath: "",
18
- cssPrefixPath: "",
19
- cssThemePrefixPath: "node_modules/@farberg/reveal-template/",
20
- slidesDestinationElement: document.querySelector("body div.reveal div.slides"),
21
- indexDocument: "00 - Introduction.md",
22
- verbose: false
14
+ // All third-party paths below are written as bare-package specifiers
15
+ // (e.g. "reveal.js/dist/reveal.mjs"). At runtime they are resolved to
16
+ // `${basePath}node_modules/${pkgPath}`. When migrating to a bundler
17
+ // (Vite, etc.), these same strings can be used directly as import
18
+ // specifiers — drop the toUrl() prefixing and they Just Work.
19
+
20
+ const revealEsmModules = [
21
+ 'reveal.js/dist/reveal.mjs', // must be first
22
+ 'reveal.js/dist/plugin/markdown.mjs',
23
+ 'reveal.js/dist/plugin/highlight.mjs',
24
+ 'reveal.js/dist/plugin/search.mjs',
25
+ 'reveal.js/dist/plugin/notes.mjs',
26
+ 'reveal.js/dist/plugin/math.mjs',
27
+ 'reveal.js/dist/plugin/zoom.mjs'
28
+ ]
29
+
30
+ // Third-party ESM deps loaded dynamically via import(). Awaited in parallel.
31
+ // `isPlugin: true` means the module's default export is a Reveal plugin and
32
+ // gets registered automatically; otherwise it's a library injected into a
33
+ // Dennis-plugin factory (see buildDennisPlugins).
34
+ const esmDeps = {
35
+ qrCreator: { path: 'qr-creator/dist/qr-creator.es6.min.js' },
36
+ fflate: { path: 'fflate/esm/browser.js' },
37
+ asciinemaPlayer: { path: 'asciinema-player/dist/index.js' },
38
+ revealMermaid: { path: 'reveal.js-mermaid-plugin/plugin/mermaid/mermaid.esm.js', isPlugin: true },
39
+ simplemenu: { path: 'reveal.js-simplemenu/plugin/simplemenu/simplemenu.esm.js', isPlugin: true }
23
40
  }
24
41
 
42
+ // Classic-script deps that publish themselves on `window` and have no ESM build.
43
+ // These are awaited via the script `load` event so their globals are defined
44
+ // before Reveal.initialize is called.
25
45
  const externalJsLibs = [
26
- 'node_modules/easyqrcodejs/dist/easy.qrcode.min.js',
27
- 'node_modules/file-saver/dist/FileSaver.min.js',
28
- 'node_modules/jszip/dist/jszip.min.js',
29
- 'node_modules/asciinema-player/dist/bundle/asciinema-player.min.js',
30
- 'node_modules/reveal.js-plugins/customcontrols/plugin.js',
31
- 'node_modules/reveal.js-plugins/chalkboard/plugin.js',
32
- 'node_modules/@fortawesome/fontawesome-free/js/all.min.js',
33
- 'node_modules/reveal.js-mermaid-plugin/plugin/mermaid/mermaid.js'
46
+ 'reveal.js-plugins/customcontrols/plugin.js', // → window.RevealCustomControls
47
+ 'reveal.js-plugins/chalkboard/plugin.js' // → window.RevealChalkboard
34
48
  ]
35
49
 
36
50
  const extraStylesheets = [
37
- { href: 'node_modules/reveal.js/dist/reveal.css' },
38
- { href: 'node_modules/reveal.js/dist/plugin/highlight/zenburn.css' },
39
- { href: 'node_modules/asciinema-player/dist/bundle/asciinema-player.css' },
40
- { href: 'node_modules/reveal.js-plugins/customcontrols/style.css' },
41
- { href: 'node_modules/reveal.js-plugins/chalkboard/style.css' },
42
- { href: 'node_modules/@fortawesome/fontawesome-free/css/all.min.css' },
51
+ { href: 'reveal.js/dist/reveal.css' },
52
+ { href: 'reveal.js/dist/plugin/highlight/zenburn.css' },
53
+ { href: 'asciinema-player/dist/bundle/asciinema-player.css' },
54
+ { href: 'reveal.js-plugins/customcontrols/style.css' },
55
+ { href: 'reveal.js-plugins/chalkboard/style.css' },
56
+ { href: '@fortawesome/fontawesome-free/css/all.min.css' }
43
57
  ]
44
58
 
45
- const extraThemeCssStylesheets = [
46
- { href: 'css/dhbw.css', id: 'theme' }
47
-
59
+ // Package-owned assets (theme + print CSS) live inside this package, NOT under
60
+ // node_modules. They're always co-located with init-reveal.js in local dev
61
+ // that's the repo root, in an npm install it's node_modules/@farberg/reveal-template/.
62
+ // Resolving against import.meta.url handles both cases identically and is the
63
+ // standard bundler-friendly pattern for package assets.
64
+ const defaultThemeCss = [
65
+ { href: new URL('./css/dhbw.css', import.meta.url).href, id: 'theme' }
48
66
  ]
49
67
 
50
- const defaultDennisPlugins = [
51
- ShowCodeSnippets, ShowToc, ShowAttribution, ShowQrCode, ShowTitle,
52
- ModifyFontSize, ShowHTMLExample, ToggleSolutionsPlugin, DirTreePlugin,
53
- PrefixUrlPlugin, AsciinemaPlugin
54
- ]
68
+ const printStylesheet = new URL('./css/dhbw-print.css', import.meta.url).href
69
+
70
+ const defaultOptions = {
71
+ revealOptions: {},
72
+ // Path prefix to the directory containing node_modules/, relative to the HTML.
73
+ // Examples: "" (HTML next to node_modules), "../" (HTML one level down).
74
+ basePath: "",
75
+ // Theme stylesheets. Defaults to this package's dhbw.css (resolved against
76
+ // import.meta.url so it works in both local-dev and npm-install layouts).
77
+ // Override with absolute or document-relative URLs to swap themes.
78
+ themeCss: defaultThemeCss,
79
+ slidesDestinationElement: document.querySelector("body div.reveal div.slides"),
80
+ indexDocument: "00 - Introduction.md",
81
+ verbose: false
82
+ }
55
83
 
56
84
  const defaultRevealOptions = {
57
85
  embedded: false,
@@ -60,7 +88,7 @@ const defaultRevealOptions = {
60
88
  // Display a presentation progress bar
61
89
  progress: true,
62
90
  // Display the page number of the current slide
63
- slideNumber: true,
91
+ slideNumber: "c/t",
64
92
  // Push each slide change to the browser history
65
93
  history: true,
66
94
  // none/fade/slide/convex/concave/zoom
@@ -92,6 +120,13 @@ const defaultRevealOptions = {
92
120
  { color: 'rgba(100,100,100,0.6)' },
93
121
  ]
94
122
  },
123
+ simplemenu: {
124
+ flat: true,
125
+ barhtml: {
126
+ header: "",
127
+ footer: "<div class='menubar bottom'><ul class='menu'></ul></div>"
128
+ }
129
+ },
95
130
  keyboard: {
96
131
  33: function () { Reveal.left(); }, // Don't go up using the presenter
97
132
  34: function () { Reveal.right(); }, // Don't go down using the presenter
@@ -119,81 +154,108 @@ const defaultRevealOptions = {
119
154
  secondaryColor: '#5c6971',
120
155
  secondaryTextColor: '#000'
121
156
  },
122
- sequence: { mirrorActors: false, useMaxWidth: true },
123
- flowchart: { useMaxWidth: true, padding: 6 }
157
+ sequence: {
158
+ mirrorActors: false,
159
+ useMaxWidth: true,
160
+ boxMargin: 15,
161
+ actorMargin: 60,
162
+ messageMargin: 45,
163
+ noteMargin: 15
164
+ },
165
+ flowchart: {
166
+ useMaxWidth: true,
167
+ htmlLabels: true,
168
+ curve: 'basis',
169
+ padding: 20,
170
+ nodeSpacing: 70,
171
+ rankSpacing: 90,
172
+ subGraphTitleMargin: { top: 8, bottom: 8 }
173
+ }
124
174
  },
125
175
 
126
176
  // Leave here
127
177
  plugins: []
128
178
  }
129
179
 
130
- async function addPrintStylesheetIfUrlContainsPrintPdf() {
131
- // If the query includes 'print-pdf', include the PDF print sheet
132
- if (window.location.search.match(/print-pdf/gi)) {
133
- console.log("Print version requested");
180
+ // Resolve a bare-package path against the configured basePath, and
181
+ // absolutize against document.baseURI so the result works identically
182
+ // for DOM tag URLs (resolved vs document) and dynamic import()
183
+ // (resolved vs the importing module URL).
184
+ function toUrl(basePath, pkgPath) {
185
+ return new URL(`${basePath}node_modules/${pkgPath}`, document.baseURI).href
186
+ }
134
187
 
135
- const link = document.createElement('link');
136
- link.rel = 'stylesheet';
137
- link.type = 'text/css';
138
- link.href = 'node_modules/@farberg/reveal-template/css/dhbw-print.css';
139
- document.getElementsByTagName('head')[0].appendChild(link);
140
- }
188
+ async function addPrintStylesheetIfUrlContainsPrintPdf(options) {
189
+ if (!window.location.search.match(/print-pdf/gi)) return
190
+
191
+ console.log("Print version requested")
192
+ const link = document.createElement('link')
193
+ link.rel = 'stylesheet'
194
+ link.type = 'text/css'
195
+ link.href = printStylesheet
196
+ document.head.appendChild(link)
141
197
  }
142
198
 
143
199
  // Resolve when window has finished loading
144
200
  function windowOnLoadPromise() {
145
- return new Promise((resolve, reject) => {
146
- window.addEventListener('load', () => resolve())
147
- })
201
+ return new Promise(resolve => window.addEventListener('load', () => resolve()))
148
202
  }
149
203
 
150
- // Load reveal and its plugins
204
+ // Load reveal core + bundled plugins
151
205
  function loadRevealAndPlugins(options) {
152
- const imports = [
153
- "dist/reveal.mjs" /*must be the first one*/,
154
- "dist/plugin/markdown.mjs",
155
- "dist/plugin/highlight.mjs",
156
- "dist/plugin/search.mjs",
157
- "dist/plugin/notes.mjs",
158
- "dist/plugin/math.mjs",
159
- "dist/plugin/zoom.mjs"
160
- ]
161
-
162
206
  if (options.verbose)
163
- console.log("Importing the following plugins: ", imports)
207
+ console.log("Importing reveal modules: ", revealEsmModules)
164
208
 
165
- return Promise.all(imports.map(i => import(options.revealPath + i)))
209
+ return Promise.all(revealEsmModules.map(p => import(toUrl(options.basePath, p))))
166
210
  }
167
211
 
168
- // Add js tags to the header and resolve
169
- async function addJsDependencies(options, externalJsLibs) {
170
- for (let file of externalJsLibs) {
171
- const script = document.createElement('script');
172
- script.src = options.jsPrefixPath + file;
173
- document.head.appendChild(script);
212
+ // Dynamically import each third-party ESM dep. Returns an object keyed by the
213
+ // same names as `esmDeps`, mapped to the imported module namespace.
214
+ // Dynamically import each esmDep in parallel. Returns:
215
+ // { deps: { [name]: module }, plugins: [defaultExports of isPlugin entries] }
216
+ async function loadEsmDeps(options) {
217
+ const loaded = await Promise.all(
218
+ Object.entries(esmDeps).map(async ([key, meta]) => {
219
+ const mod = await import(toUrl(options.basePath, meta.path))
220
+ return { key, mod, meta }
221
+ })
222
+ )
223
+ return {
224
+ deps: Object.fromEntries(loaded.map(({ key, mod }) => [key, mod])),
225
+ plugins: loaded.filter(({ meta }) => meta.isPlugin).map(({ mod }) => mod.default)
174
226
  }
175
227
  }
176
228
 
177
- // Add CSSs tags to the header and resolve
178
- async function addCssDependencies(options, cssFiles, themeCssFiles) {
229
+ // Inject classic <script> tags and await each one's load event so dependent
230
+ // globals (window.RevealChalkboard, etc.) are defined before Reveal init.
231
+ function addJsDependencies(options) {
232
+ return Promise.all(externalJsLibs.map(pkgPath => new Promise((resolve, reject) => {
233
+ const script = document.createElement('script')
234
+ script.src = toUrl(options.basePath, pkgPath)
235
+ script.onload = () => resolve()
236
+ script.onerror = () => reject(new Error(`Failed to load ${script.src}`))
237
+ document.head.appendChild(script)
238
+ })))
239
+ }
240
+
241
+ // Add <link rel="stylesheet"> tags for each CSS file
242
+ function addCssDependencies(options) {
179
243
  function addCssElement(href, id) {
180
- const cssEl = document.createElement('link');
244
+ const cssEl = document.createElement('link')
181
245
  cssEl.rel = "stylesheet"
182
246
  cssEl.href = href
183
- if (id)
184
- cssEl.id = id
185
-
186
- document.head.appendChild(cssEl);
247
+ if (id) cssEl.id = id
248
+ document.head.appendChild(cssEl)
187
249
  }
188
250
 
189
- for (let css of cssFiles) {
190
- addCssElement(options.cssPrefixPath + css.href, css.id)
191
- }
192
-
193
- for (let css of themeCssFiles) {
194
- addCssElement(options.cssThemePrefixPath + css.href, css.id)
195
- }
251
+ for (const css of extraStylesheets)
252
+ addCssElement(toUrl(options.basePath, css.href), css.id)
196
253
 
254
+ // Theme CSS hrefs are used as-is. Defaults are absolute URLs (resolved via
255
+ // import.meta.url so they work in both local-dev and npm-install layouts).
256
+ // User overrides pass document-relative or absolute URLs directly.
257
+ for (const css of options.themeCss)
258
+ addCssElement(css.href, css.id)
197
259
  }
198
260
 
199
261
  function getDocumentToLoadOrRedirectToIndexDocument(options) {
@@ -221,6 +283,24 @@ function addMarkdownSectionToPresentation(doc, options) {
221
283
  options.slidesDestinationElement.appendChild(mdel)
222
284
  }
223
285
 
286
+ // Build the Dennis-plugins array, injecting ESM deps into the factories that
287
+ // need them. Plugins that take no deps stay as static factory imports.
288
+ function buildDennisPlugins(deps) {
289
+ return [
290
+ ShowCodeSnippets,
291
+ ShowToc,
292
+ ShowAttribution,
293
+ ShowQrCode(deps.qrCreator.default),
294
+ ShowTitle,
295
+ ModifyFontSize,
296
+ ShowHTMLExample,
297
+ ToggleSolutionsPlugin,
298
+ DirTreePlugin(deps.fflate),
299
+ PrefixUrlPlugin,
300
+ AsciinemaPlugin(deps.asciinemaPlayer.create)
301
+ ]
302
+ }
303
+
224
304
  export function initReveal(opts) {
225
305
  // Generate options and include defaults (later sources' properties overwrite earlier ones)
226
306
  const options = Object.assign({}, defaultOptions, opts)
@@ -228,19 +308,22 @@ export function initReveal(opts) {
228
308
  // Load dependencies and then initialize Reveal
229
309
  Promise.all([
230
310
  loadRevealAndPlugins(options),
231
- addJsDependencies(options, externalJsLibs),
232
- addCssDependencies(options, extraStylesheets, extraThemeCssStylesheets),
233
- addPrintStylesheetIfUrlContainsPrintPdf(),
311
+ loadEsmDeps(options),
312
+ addJsDependencies(options),
313
+ addCssDependencies(options),
314
+ addPrintStylesheetIfUrlContainsPrintPdf(options),
234
315
  windowOnLoadPromise()
235
316
  ]).then(async values => {
236
- //Get the first element from the array, this is the Reveal module
237
- const modules = values[0].map(m => m.default)
238
- const Reveal = modules.shift();
317
+ const [revealModules, { deps, plugins: esmPlugins }] = values
318
+
319
+ // First entry from reveal modules is Reveal itself
320
+ const modules = revealModules.map(m => m.default)
321
+ const Reveal = modules.shift()
239
322
 
240
- //Make it globally available
323
+ // Make it globally available
241
324
  window.Reveal = Reveal
242
325
 
243
- //Add markdown doc to presentation
326
+ // Add markdown doc to presentation
244
327
  const doc = getDocumentToLoadOrRedirectToIndexDocument(options)
245
328
 
246
329
  if (doc) {
@@ -252,11 +335,11 @@ export function initReveal(opts) {
252
335
  //Add plugins
253
336
  finalOptions.plugins = [
254
337
  ...modules,
255
- ...defaultDennisPlugins,
338
+ ...buildDennisPlugins(deps),
339
+ ...esmPlugins,
256
340
  ...finalOptions.plugins,
257
- RevealMermaid,
258
- RevealChalkboard,
259
- RevealCustomControls
341
+ window.RevealChalkboard,
342
+ window.RevealCustomControls
260
343
  ]
261
344
 
262
345
  if (options.verbose)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farberg/reveal-template",
3
- "version": "1.1.18",
3
+ "version": "1.1.20",
4
4
  "homepage": "https://github.com/pfisterer/reveal-template",
5
5
  "description": "Reveal.js template for Dennis' lectures",
6
6
  "main": "index.js",
@@ -18,15 +18,15 @@
18
18
  "@fortawesome/fontawesome-free": "^7.2.0",
19
19
  "asciinema-player": "^3.15.1",
20
20
  "connect": "^3.7.0",
21
- "easyqrcodejs": "^4.6.2",
22
- "file-saver": "^2.0.5",
23
- "jszip": "^3.10.1",
24
- "mermaid": "^11.14.0",
21
+ "fflate": "^0.8.3",
22
+ "mermaid": "^11.15.0",
25
23
  "pdf-merger-js": "^5.1.2",
26
- "puppeteer": "^24.42.0",
24
+ "puppeteer": "^25.0.2",
25
+ "qr-creator": "^1.0.0",
27
26
  "reveal.js": "^6.0.1",
28
27
  "reveal.js-mermaid-plugin": "^11.12.3",
29
28
  "reveal.js-plugins": "^4.6.0",
29
+ "reveal.js-simplemenu": "^2.0.3",
30
30
  "serve-static": "^2.2.1"
31
31
  }
32
32
  }
@@ -1,11 +1,9 @@
1
- function initSlide(slide) {
1
+ function initSlide(asciinemaCreate, slide) {
2
2
  let players = []
3
3
 
4
4
  let asciinemaElements = slide.getElementsByTagName("asciinema")
5
5
 
6
6
  for (let el of asciinemaElements) {
7
- //console.log("Found asciinema element: ", el)
8
-
9
7
  //Make element invisible
10
8
  el.style.display = "none"
11
9
 
@@ -16,8 +14,7 @@ function initSlide(slide) {
16
14
 
17
15
  div.setAttribute('data-farberg-asciinema', 'true')
18
16
 
19
- //console.log("Playing", source, "with options", conf)
20
- players.push(AsciinemaPlayer.create(source, div, JSON.parse(conf)))
17
+ players.push(asciinemaCreate(source, div, JSON.parse(conf)))
21
18
 
22
19
  el.parentNode.insertBefore(div, el.nextSibling)
23
20
  }
@@ -38,7 +35,7 @@ function destroyPlayer(slide, players) {
38
35
  players.forEach(player => player.dispose())
39
36
  }
40
37
 
41
- export default () => {
38
+ export default (asciinemaCreate) => {
42
39
 
43
40
  return {
44
41
  id: 'asciinema',
@@ -46,13 +43,13 @@ export default () => {
46
43
  deck.on('ready', () => {
47
44
  let currentPlayers = undefined
48
45
 
49
- currentPlayers = initSlide(deck.getCurrentSlide())
46
+ currentPlayers = initSlide(asciinemaCreate, deck.getCurrentSlide())
50
47
 
51
48
  deck.addEventListener('slidechanged', function (event) {
52
49
  if (event.previousSlide)
53
50
  destroyPlayer(event.previousSlide, currentPlayers)
54
51
 
55
- currentPlayers = initSlide(event.currentSlide)
52
+ currentPlayers = initSlide(asciinemaCreate, event.currentSlide)
56
53
  })
57
54
  })
58
55
  }