diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7810fb7..0e38deb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,8 +13,9 @@ before_script: sandbox: script: + - npn run build:pdf - hugo -F - - node themes/devfest-theme-hugo/minify.js + - npn run build:minify - firebase use default - firebase deploy --token "$FIREBASE_SANDBOX_TOKEN" artifacts: @@ -27,8 +28,9 @@ prod: variables: HUGO_ENV: production script: + - npn run build:pdf - hugo --baseURL https://2019.devfesttoulouse.fr/ - - node themes/devfest-theme-hugo/minify.js + - npn run build:minify - firebase use prod - firebase deploy --token "$FIREBASE_PROD_TOKEN" artifacts: diff --git a/package.json b/package.json index 2f7908a..0f0656b 100644 --- a/package.json +++ b/package.json @@ -5,16 +5,17 @@ "author": "Igor Laborie ", "license": "Apache-2.0", "scripts": { - "generate:pdf": "node tools/pdf.js", "prebuild": "hugo", "build:minify": "node tools/minify.js", - "build": "run-p build:*" + "build:pdf": "node tools/pdf.js", + "build": "run-s build:*" }, "devDependencies": { "glob": "^7.1.4", "html-minifier": "^4.0.0", "npm-run-all": "^4.1.5", - "plop-logger": "^2.3.0", - "puppeteer": "^1.19.0" + "plop-logger": "^2.6.0", + "puppeteer": "^1.19.0", + "serve-handler": "^6.1.1" } } diff --git a/static/schedule/schedule.pdf b/static/schedule/schedule.pdf index 4954c0d..0fab16d 100644 Binary files a/static/schedule/schedule.pdf and b/static/schedule/schedule.pdf differ diff --git a/tools/pdf.js b/tools/pdf.js index 73b5fc4..5f0cc3f 100644 --- a/tools/pdf.js +++ b/tools/pdf.js @@ -1,43 +1,96 @@ const puppeteer = require('puppeteer'); const {Logger, LogLevel} = require('plop-logger'); const {colorEmojiConfig} = require('plop-logger/lib/extra/colorEmojiConfig'); +const handler = require('serve-handler'); +const http = require('http'); Logger.config = colorEmojiConfig; Logger.config.defaultLevel = LogLevel.Debug; const logger = Logger.getLogger('pdf'); +// Configuration +const serverConf = { + port: 8765, + options: { + "public": "./public" + } +}; +const browserConf = { + defaultViewport: {width: 1280, height: 1700}, + margin: { + top: "0cm", + right: "0cm", + bottom: "0cm", + left: "0cm" + }, + devtools: false +}; + +async function startServer({port, options}) { + return new Promise((resolve, reject) => { + const server = http.createServer((request, response) => + handler(request, response, options)); + + server.listen(port, err => { + if (err) { + logger.error('Fail to start server', err); + reject(err); + } else { + logger.info('Server started', () => `http://localhost:${port}`); + resolve(server); + } + }); + }); +} + +async function stopServer(server) { + return new Promise((resolve, reject) => { + logger.info('Stopping server...'); + server.close(err => { + if (err) { + logger.error('Fail to stop server', err); + reject(err); + } else { + logger.info('Server stopped'); + resolve(); + } + }); + }); +} + +async function cleanupBeforePrint(page) { + const toHide = [ + 'body > header', + 'body > footer', + 'main .hero', + ]; + + await page.$$eval(toHide.join(','), elts => + elts.forEach(elt => + elt.parentNode.removeChild(elt))); + + await page.addStyleTag({ + content: '@page { size: auto; }', + }); +} + (async () => { + const server = await startServer(serverConf); + logger.info("launch puppeteer browser"); - const defaultViewport = {width: 1280, height: 1700}; - const devtools = false; - const browser = await puppeteer.launch({devtools, defaultViewport}); + const browser = await puppeteer.launch(browserConf); try { logger.info("open new page"); const page = await browser.newPage(); logger.debug("opened new page"); const file = 'schedule/index.html'; - const url = `http://localhost:1313/${file}`; + const url = `http://localhost:${serverConf.port}/${file}`; logger.info("go to", url); const pageResponse = await page.goto(url, {waitUntil: 'networkidle2'}); - logger.debug("gone", pageResponse.statusText()); - - const toHide = [ - 'body>header', - 'body>footer', - 'main .hero', - ]; - await page.$$eval(toHide.join(','), function (elts) { - // debugger; - elts.forEach(elt => { - elt.parentNode.removeChild(elt); - // elt.style.display = 'none'; - }); - }); + logger.debug("done", pageResponse.statusText()); - await page.addStyleTag({ - content: '@page { size: auto; }', - }); + await cleanupBeforePrint(page); logger.info('export pdf'); const path = 'static/schedule/schedule.pdf'; @@ -53,5 +106,6 @@ const logger = Logger.getLogger('pdf'); } finally { logger.info('close puppeteer browser'); await browser.close(); + await stopServer(server); } })(); diff --git a/yarn.lock b/yarn.lock index 0b2baf3..f6b6dd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -44,6 +44,11 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + camel-case@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" @@ -100,6 +105,11 @@ concat-stream@1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= + core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -199,6 +209,13 @@ extract-zip@^1.6.6: mkdirp "0.5.1" yauzl "2.4.1" +fast-url-parser@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= + dependencies: + punycode "^1.3.2" + fd-slicer@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" @@ -358,12 +375,24 @@ memorystream@^0.3.1: resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== + dependencies: + mime-db "~1.33.0" + mime@^2.0.3: version "2.4.4" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== -minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -461,6 +490,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-is-inside@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -471,6 +505,11 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-to-regexp@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" + integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -493,10 +532,10 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= -plop-logger@^2.3.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/plop-logger/-/plop-logger-2.5.0.tgz#3a80cf4edb98cc6c91a83cc39ba6eff9343308cd" - integrity sha512-sudMgIddrxQYw/UpLWjK//CcA4kCCTr87OWTPlf8gLCoBni2vodp5BbhCH6lMXXINUD//5yPmA9jAMwT3tUSCA== +plop-logger@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/plop-logger/-/plop-logger-2.6.0.tgz#34bba0f7bdb0af80f991f1901c380bfa343645a7" + integrity sha512-N1KJ/YxJlLK4flh9tjfiDoYLs1vR/Bssr0k8a9BNJAMq1BYnn1dAqQLI2XSKm9Pc35CjfGHazKxdh4AkAWCprQ== dependencies: ansi-colors "^4.1.1" tslib "^1.10.0" @@ -516,6 +555,11 @@ proxy-from-env@^1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + puppeteer@^1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-1.19.0.tgz#e3b7b448c2c97933517078d7a2c53687361bebea" @@ -530,6 +574,11 @@ puppeteer@^1.19.0: rimraf "^2.6.1" ws "^6.1.0" +range-parser@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -581,6 +630,20 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +serve-handler@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.1.tgz#e4470ba9f4294c970012f5b5428c6582225106f6" + integrity sha512-LQPvxGia2TYqyMkHKH4jW9jx6jlQUMcWz6gJavZ3+4vsnB+SaWbYTncb9YsK5YBR6SlvyumREZJAzLw8VaFAUQ== + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.0.4" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"