@farberg/reveal-template 1.0.62 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farberg/reveal-template",
3
- "version": "1.0.62",
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
  }
@@ -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,64 @@ 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) => {
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
- 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)
112
+ const browser = await puppeteer.launch({ headless: 'new' })
113
+ const page = await browser.newPage();
172
114
 
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);
115
+ await page.goto(todo.presentation_url, { timeout: 5000, waitUntil: ['load', 'domcontentloaded'] });
116
+ await page.waitForSelector('div.lecturetitle > h1')
175
117
 
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
- })
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
- //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)
140
+ async function merge_pdfs(todos, out_file) {
141
+ const merger = new PDFMerger()
198
142
 
199
- let p = spawn_merge_to_single_pdf(pdfs, out_file, pdf_dir)
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
- p.on('close', code => {
202
- console.log(`PDF merge exited with code ${code} `)
203
- resolve(code)
204
- process.exit(0)
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
- 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
- })
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
+ })