@farberg/reveal-template 1.0.62 → 1.0.64

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farberg/reveal-template",
3
- "version": "1.0.62",
3
+ "version": "1.0.64",
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
  }
@@ -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 { spawn } = require('child_process');
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://${host}:${port}`
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,70 @@ function delete_stale_pdf_files(todos, pdf_dir, combined_pdf_name) {
163
98
  })
164
99
  }
165
100
 
166
- function run_todos(todos, maxProcessesRunning) {
167
- return new Promise((resolve, reject) => {
168
-
169
- let interval = setInterval(() => {
170
- const running_processes = todos.filter(todo => todo.process && todo.process.exitCode == null)
171
- const waiting_processes = todos.filter(todo => !todo.process)
172
-
173
- //console.log(`Running ${running_processes.length}, waiting ${waiting_processes.length}`)
174
- //console.log("todos_that_require_action", todos_that_require_action); console.log("running_processes", running_processes); console.log("waiting_processes", waiting_processes);
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
+ }
111
+
112
+ const browser = await puppeteer.launch({ headless: 'new' })
113
+ const page = await browser.newPage();
114
+
115
+ await page.goto(todo.presentation_url, { timeout: 5000, waitUntil: ['load', 'domcontentloaded'] });
116
+
117
+ const selector = 'div.lecturetitle > h1'
118
+ try {
119
+ await page.waitForSelector(selector, { timeout: 5000 })
120
+ } catch (e) {
121
+ console.error(`Unable to find selector ${selector} on ${todo.presentation_url}`)
122
+ }
175
123
 
176
- if (running_processes.length < maxProcessesRunning && waiting_processes.length > 0) {
177
- console.log(`Starting next process: ${waiting_processes[0].md_file}`)
178
- waiting_processes[0].start_conversion()
179
-
180
- } else if (running_processes.length === 0 && waiting_processes.length === 0) {
181
- console.log(`No more running/required processes, done converting.`)
182
- clearInterval(interval)
183
- resolve()
184
- }
185
- }, 300)
186
-
187
- })
124
+ if (verbose)
125
+ console.log(`Converting ${todo.md_file} to ${todo.pdf_file} using ${todo.presentation_url}`)
126
+
127
+ const optionsa4 = {
128
+ format: 'A4',
129
+ printBackground: true,
130
+ landscape: true,
131
+ margin: {
132
+ top: '0.25cm',
133
+ bottom: '0.25cm',
134
+ left: '0.25cm',
135
+ right: '0.25cm'
136
+ },
137
+ path: todo.pdf_file
138
+ }
139
+
140
+ const pdf = await page.pdf(optionsa4);
141
+ await browser.close();
142
+ return pdf
188
143
  }
189
144
 
190
- function merge_pdfs(todos, out_file) {
191
- return new Promise((resolve, reject) => {
192
145
 
193
- //Merge to a single PDF (only if the PDFs have more than 0 bytes)
194
- let pdfs = todos
195
- .filter(todo => fs.existsSync(todo.pdf_file))
196
- .filter(todo => fs.statSync(todo.pdf_file).size > 0)
197
- .map(todo => todo.pdf_name)
146
+ async function merge_pdfs(todos, out_file) {
147
+ const merger = new PDFMerger()
198
148
 
199
- let p = spawn_merge_to_single_pdf(pdfs, out_file, pdf_dir)
149
+ let pdfs = todos
150
+ .filter(todo => fs.existsSync(todo.pdf_file))
151
+ .filter(todo => fs.statSync(todo.pdf_file).size > 0)
152
+ .map(todo => todo.pdf_file)
200
153
 
201
- p.on('close', code => {
202
- console.log(`PDF merge exited with code ${code} `)
203
- resolve(code)
204
- process.exit(0)
205
- })
206
- })
154
+ for (const pdf of pdfs) {
155
+ //if (verbose)console.log(`Adding ${pdf} to merged file`)
156
+ await merger.add(pdf)
157
+ }
158
+ if (verbose)
159
+ console.log(`Saving merged file to ${out_file}`)
160
+ await merger.save(out_file);
207
161
  }
208
162
 
209
- //Update docker image first
210
- update_docker_image().then(code => {
211
- if (verbose)
212
- console.log("Docker image updated")
213
163
 
164
+ async function main() {
214
165
  //Start an embedded web server to load the slides from
215
166
  const app = start_web_server();
216
167
 
@@ -222,9 +173,17 @@ update_docker_image().then(code => {
222
173
 
223
174
  delete_stale_pdf_files(todos, pdf_dir, combined_pdf_name)
224
175
 
225
- run_todos(todos_that_require_action, maxProcessesRunning).then(() => {
226
- console.log("Merging pdfs");
227
- merge_pdfs(todos, combined_pdf_name)
228
- console.log("Done")
229
- })
230
- })
176
+ for (const todo of todos_that_require_action) {
177
+ await convert_to_pdf_single(todo)
178
+ }
179
+
180
+ await merge_pdfs(todos, combined_pdf_name)
181
+ }
182
+
183
+ main().then(() => {
184
+ console.log("Done")
185
+ process.exit(0)
186
+ }).catch(e => {
187
+ console.error(e)
188
+ process.exit(1)
189
+ })