@farberg/reveal-template 1.0.61 → 1.0.63
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 +19 -13
- package/package.json +4 -2
- package/scripts/generate_pdfs.js +65 -112
package/init-reveal.js
CHANGED
|
@@ -198,23 +198,29 @@ export function initReveal(opts) {
|
|
|
198
198
|
window.Reveal = Reveal
|
|
199
199
|
|
|
200
200
|
//Add markdown doc to presentation
|
|
201
|
-
|
|
201
|
+
const doc = getDocumentToLoadOrRedirectToIndexDocument(options)
|
|
202
202
|
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
if (doc) {
|
|
204
|
+
addMarkdownSectionToPresentation(doc, options);
|
|
205
205
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
...modules,
|
|
209
|
-
...defaultDennisPlugins,
|
|
210
|
-
window.RevealChalkboard,
|
|
211
|
-
...finalOptions.plugins
|
|
212
|
-
]
|
|
206
|
+
//Initialize Reveal
|
|
207
|
+
const finalOptions = Object.assign(defaultRevealOptions, options.revealOptions);
|
|
213
208
|
|
|
214
|
-
|
|
215
|
-
|
|
209
|
+
//Add plugins
|
|
210
|
+
finalOptions.plugins = [
|
|
211
|
+
...modules,
|
|
212
|
+
...defaultDennisPlugins,
|
|
213
|
+
window.RevealChalkboard,
|
|
214
|
+
...finalOptions.plugins
|
|
215
|
+
]
|
|
216
216
|
|
|
217
|
-
|
|
217
|
+
if (options.verbose)
|
|
218
|
+
console.log("Invoking Reveal.initialize with options: ", finalOptions)
|
|
219
|
+
|
|
220
|
+
Reveal.initialize(finalOptions);
|
|
221
|
+
} else {
|
|
222
|
+
console.error("No document to load, aborting");
|
|
223
|
+
}
|
|
218
224
|
|
|
219
225
|
}).catch(error => {
|
|
220
226
|
console.error("Unable to load dependencies: ", error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farberg/reveal-template",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.63",
|
|
4
4
|
"homepage": "https://github.com/pfisterer/reveal-template",
|
|
5
5
|
"description": "Reveal.js template for Dennis' lectures",
|
|
6
6
|
"main": "index.js",
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
"reveal.js": "^4.5.0",
|
|
23
23
|
"reveal.js-plugins": "^4.2.0",
|
|
24
24
|
"serve-static": "^1.15.0",
|
|
25
|
-
"asciinema-player": "^3.5.0"
|
|
25
|
+
"asciinema-player": "^3.5.0",
|
|
26
|
+
"pdf-merger-js": "^4.3.0",
|
|
27
|
+
"puppeteer": "^21.5.2"
|
|
26
28
|
}
|
|
27
29
|
}
|
package/scripts/generate_pdfs.js
CHANGED
|
@@ -4,9 +4,9 @@ const serveStatic = require('serve-static')
|
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const fs = require('fs');
|
|
7
|
-
const
|
|
7
|
+
const puppeteer = require('puppeteer')
|
|
8
|
+
const PDFMerger = require('pdf-merger-js');
|
|
8
9
|
const { combined_pdf, pdf_exists_and_is_newer_than_markdown } = require('./helpers')
|
|
9
|
-
const decktape_image = 'astefanutti/decktape:3.7'
|
|
10
10
|
|
|
11
11
|
const cwd = process.cwd()
|
|
12
12
|
const slides_dir = cwd
|
|
@@ -17,8 +17,7 @@ const verbose = true
|
|
|
17
17
|
const package_json = JSON.parse(fs.readFileSync('package.json'))
|
|
18
18
|
const combined_pdf_name = combined_pdf(package_json)
|
|
19
19
|
const args = process.argv.slice(2);
|
|
20
|
-
const url = args[0] ? args[0] : `http
|
|
21
|
-
const maxProcessesRunning = Math.max(Math.floor(os.cpus().length / 2, 1))
|
|
20
|
+
const url = args[0] ? args[0] : `http://localhost:${port}`
|
|
22
21
|
|
|
23
22
|
function start_web_server() {
|
|
24
23
|
var app = connect();
|
|
@@ -32,56 +31,6 @@ function start_web_server() {
|
|
|
32
31
|
return app
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
function update_docker_image() {
|
|
36
|
-
return new Promise((resolve, reject) => {
|
|
37
|
-
|
|
38
|
-
let cmd = "docker"
|
|
39
|
-
let args = ["pull", decktape_image]
|
|
40
|
-
let cmdLine = `${cmd} ${args.reduce((a, b) => `${a} '${b}'`, "")}`
|
|
41
|
-
|
|
42
|
-
if (verbose)
|
|
43
|
-
console.log(`Running ${cmdLine}`)
|
|
44
|
-
|
|
45
|
-
const update_process = spawn(cmd, args)
|
|
46
|
-
|
|
47
|
-
update_process.on('close', code => resolve(code))
|
|
48
|
-
})
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function spawn_convert_md_to_pdf(url, pdf_dir, pdf_name) {
|
|
52
|
-
let cmd = "docker"
|
|
53
|
-
let args = ["run", "--rm", "-u", `${os.userInfo().uid}`, "-v", `${pdf_dir}:/slides`, decktape_image, "--load-pause", "2000", "--pause", "500", "-s", "1200x800", "automatic", url, `/slides/${path.basename(pdf_name)}`]
|
|
54
|
-
|
|
55
|
-
let cmdLine = `${cmd} ${args.reduce((a, b) => `${a} '${b}'`, "")}`
|
|
56
|
-
|
|
57
|
-
if (verbose)
|
|
58
|
-
console.log(`Running ${cmdLine}`)
|
|
59
|
-
|
|
60
|
-
return spawn(cmd, args)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function spawn_merge_to_single_pdf(pdfs, pdf, pdf_dir) {
|
|
64
|
-
let output_pdf = `/slides/${path.basename(pdf)}`
|
|
65
|
-
let cmd = "docker"
|
|
66
|
-
let args = ["run", "--rm", "-v", `${pdf_dir}:/slides`, "agileek/pdftk"]
|
|
67
|
-
args = args.concat(
|
|
68
|
-
pdfs.map(pdf_file => '/slides/' + path.basename(pdf_file)),
|
|
69
|
-
["cat", "output", output_pdf]
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
let cmdLine = `${cmd} ${args.reduce((a, b) => `${a} '${b}'`, "")}`
|
|
73
|
-
if (verbose)
|
|
74
|
-
console.log(`Running ${cmdLine}`)
|
|
75
|
-
|
|
76
|
-
return spawn(cmd, args)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function touch_file(path) {
|
|
80
|
-
const time = new Date();
|
|
81
|
-
if (fs.existsSync(path))
|
|
82
|
-
fs.utimesSync(path, time, time);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
34
|
function get_todos(md_dir, pdf_dir, url) {
|
|
86
35
|
//Get list of markdown files
|
|
87
36
|
let md_files = fs.readdirSync(md_dir)
|
|
@@ -101,7 +50,7 @@ function get_todos(md_dir, pdf_dir, url) {
|
|
|
101
50
|
let pdf_exists = fs.existsSync(pdf_file)
|
|
102
51
|
let pdf_size = pdf_exists ? fs.statSync(pdf_file)["size"] : 0;
|
|
103
52
|
let pdf_newer = pdf_size > 0 ? pdf_exists_and_is_newer_than_markdown(md_file, pdf_file, verbose) : 0
|
|
104
|
-
let presentation_url = `${url}/index.html?${encodeURIComponent(md_file)}
|
|
53
|
+
let presentation_url = `${url}/index.html?${encodeURIComponent(md_file)}/print-pdf#/`
|
|
105
54
|
|
|
106
55
|
let o = {
|
|
107
56
|
md_file,
|
|
@@ -112,25 +61,11 @@ function get_todos(md_dir, pdf_dir, url) {
|
|
|
112
61
|
pdf_newer,
|
|
113
62
|
requires_conversion: !pdf_exists || !pdf_newer,
|
|
114
63
|
presentation_url,
|
|
115
|
-
start_conversion: () => {
|
|
116
|
-
o.process = spawn_convert_md_to_pdf(presentation_url, pdf_dir, pdf_name)
|
|
117
|
-
o.process.stdout.on('data', data => o.stdout.push(data))
|
|
118
|
-
o.process.stderr.on('data', data => o.stderr.push(data))
|
|
119
|
-
o.process.on('close', code => {
|
|
120
|
-
touch_file(pdf_file)
|
|
121
|
-
console.log(`Processed file ${md_file}, exited with code ${code}`)
|
|
122
|
-
})
|
|
123
|
-
},
|
|
124
|
-
process: null,
|
|
125
|
-
stdout: [],
|
|
126
|
-
stderr: []
|
|
127
64
|
}
|
|
128
65
|
|
|
129
66
|
return o
|
|
130
67
|
})
|
|
131
68
|
|
|
132
|
-
//if (verbose) console.log("All todos (not filtered):", todos)
|
|
133
|
-
|
|
134
69
|
const todos_that_require_action = todos.filter(todo => todo.requires_conversion === true)
|
|
135
70
|
const todos_that_dont_require_action = todos.filter(todo => todo.requires_conversion === false)
|
|
136
71
|
return { todos, todos_that_require_action, todos_that_dont_require_action };
|
|
@@ -163,54 +98,64 @@ function delete_stale_pdf_files(todos, pdf_dir, combined_pdf_name) {
|
|
|
163
98
|
})
|
|
164
99
|
}
|
|
165
100
|
|
|
166
|
-
function
|
|
167
|
-
|
|
101
|
+
async function convert_to_pdf_single(todo) {
|
|
102
|
+
async function waitForEvent(page, event, timeout = 2500) {
|
|
103
|
+
return Promise.race([
|
|
104
|
+
page.evaluate(
|
|
105
|
+
event => new Promise(resolve => document.addEventListener(event, resolve, { once: true })),
|
|
106
|
+
event
|
|
107
|
+
),
|
|
108
|
+
new Promise(r => setTimeout(r, timeout))
|
|
109
|
+
])
|
|
110
|
+
}
|
|
168
111
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const waiting_processes = todos.filter(todo => !todo.process)
|
|
112
|
+
const browser = await puppeteer.launch({ headless: 'new' })
|
|
113
|
+
const page = await browser.newPage();
|
|
172
114
|
|
|
173
|
-
|
|
174
|
-
|
|
115
|
+
await page.goto(todo.presentation_url, { timeout: 5000, waitUntil: ['load', 'domcontentloaded'] });
|
|
116
|
+
await page.waitForSelector('div.lecturetitle > h1')
|
|
175
117
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
118
|
+
if (verbose)
|
|
119
|
+
console.log(`Converting ${todo.md_file} to ${todo.pdf_file} using ${todo.presentation_url}`)
|
|
120
|
+
|
|
121
|
+
const optionsa4 = {
|
|
122
|
+
format: 'A4',
|
|
123
|
+
printBackground: true,
|
|
124
|
+
landscape: true,
|
|
125
|
+
margin: {
|
|
126
|
+
top: '0.25cm',
|
|
127
|
+
bottom: '0.25cm',
|
|
128
|
+
left: '0.25cm',
|
|
129
|
+
right: '0.25cm'
|
|
130
|
+
},
|
|
131
|
+
path: todo.pdf_file
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const pdf = await page.pdf(optionsa4);
|
|
135
|
+
await browser.close();
|
|
136
|
+
return pdf
|
|
188
137
|
}
|
|
189
138
|
|
|
190
|
-
function merge_pdfs(todos, out_file) {
|
|
191
|
-
return new Promise((resolve, reject) => {
|
|
192
139
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
.filter(todo => fs.existsSync(todo.pdf_file))
|
|
196
|
-
.filter(todo => fs.statSync(todo.pdf_file).size > 0)
|
|
197
|
-
.map(todo => todo.pdf_name)
|
|
140
|
+
async function merge_pdfs(todos, out_file) {
|
|
141
|
+
const merger = new PDFMerger()
|
|
198
142
|
|
|
199
|
-
|
|
143
|
+
let pdfs = todos
|
|
144
|
+
.filter(todo => fs.existsSync(todo.pdf_file))
|
|
145
|
+
.filter(todo => fs.statSync(todo.pdf_file).size > 0)
|
|
146
|
+
.map(todo => todo.pdf_file)
|
|
200
147
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
148
|
+
for (const pdf of pdfs) {
|
|
149
|
+
//if (verbose)console.log(`Adding ${pdf} to merged file`)
|
|
150
|
+
await merger.add(pdf)
|
|
151
|
+
}
|
|
152
|
+
if (verbose)
|
|
153
|
+
console.log(`Saving merged file to ${out_file}`)
|
|
154
|
+
await merger.save(out_file);
|
|
207
155
|
}
|
|
208
156
|
|
|
209
|
-
//Update docker image first
|
|
210
|
-
update_docker_image().then(code => {
|
|
211
|
-
if (verbose)
|
|
212
|
-
console.log("Docker image updated")
|
|
213
157
|
|
|
158
|
+
async function main() {
|
|
214
159
|
//Start an embedded web server to load the slides from
|
|
215
160
|
const app = start_web_server();
|
|
216
161
|
|
|
@@ -222,9 +167,17 @@ update_docker_image().then(code => {
|
|
|
222
167
|
|
|
223
168
|
delete_stale_pdf_files(todos, pdf_dir, combined_pdf_name)
|
|
224
169
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
170
|
+
for (const todo of todos_that_require_action) {
|
|
171
|
+
await convert_to_pdf_single(todo)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
await merge_pdfs(todos, combined_pdf_name)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
main().then(() => {
|
|
178
|
+
console.log("Done")
|
|
179
|
+
process.exit(0)
|
|
180
|
+
}).catch(e => {
|
|
181
|
+
console.error(e)
|
|
182
|
+
process.exit(1)
|
|
183
|
+
})
|