Skip to content

Commit

Permalink
Merge pull request #1 from udondan/improvements
Browse files Browse the repository at this point in the history
Various improvements (options, server, re-using image)
  • Loading branch information
fifsky authored Nov 11, 2019
2 parents d2a5ac6 + 5d8f02e commit 44d9778
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 244 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# HTML to PDF

A github action that converts HTML files to PDF [GitHub Actions](https://github.com/features/actions).

A [GitHub Action](https://github.com/features/actions) that converts a HTML file to PDF.

## ✨ Example Usage

Expand All @@ -11,4 +10,7 @@ A github action that converts HTML files to PDF [GitHub Actions](https://github.
with:
htmlFile: ./public/index.html
outputFile: ./public/resume.pdf
pdfOptions: '{"format": "A4", "margin": {"top": "10mm", "left": "10mm", "right": "10mm", "bottom": "10mm"}}'
```
`pdfOptions` relate to [puppeteers page.pdf options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagepdfoptions)
24 changes: 16 additions & 8 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
name: 'HTML to PDF'
description: 'Node module that converts HTML files to PDFs.'
author: '[email protected]'
name: "HTML to PDF"
description: "Converts HTML file to PDF."
author: "[email protected]"
inputs:
htmlFile:
description: 'html file path'
description: "html file path"
required: true

outputFile:
description: 'output file path'
description: "output file path"
required: true

pdfOptions:
description: |
PDF options as described here:
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagepdfoptions -
Needs to be in JSON format, e.g. `{"format": "A4", "pageRanges": "1"}`
required: false
default: "{}"

runs:
using: 'docker'
image: 'Dockerfile'
using: "docker"
image: "Dockerfile"

branding:
color: "blue"
icon: "file"
icon: "file"
37 changes: 5 additions & 32 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
FROM node:10-alpine
FROM buildkite/puppeteer

LABEL MAINTAINER="Xudong Cai <[email protected]>"
ENV TZ=Asia/Shanghai
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true

#[email protected]
RUN sed -i 's!http://dl-cdn.alpinelinux.org/!https://mirrors.aliyun.com/!g' /etc/apk/repositories \
&& apk update && apk upgrade && \
echo @edge https://mirrors.aliyun.com/alpine/edge/community >> /etc/apk/repositories && \
echo @edge https://mirrors.aliyun.com/alpine/edge/main >> /etc/apk/repositories && \
apk --no-cache add \
tzdata \
curl \
ca-certificates \
chromium@edge \
nss@edge \
fontconfig \
freetype \
ttf-dejavu \
ttf-droid \
ttf-freefont \
mesa-egl \
mesa-gles \
&& mkdir /usr/lib/chromium/swiftshader/ \
&& cp /usr/lib/libGLESv2.so.2 /usr/lib/chromium/swiftshader/libGLESv2.so \
&& cp /usr/lib/libEGL.so.1 /usr/lib/chromium/swiftshader/libEGL.so \
&& ln -sf /usr/bin/chromium-browser /usr/local/bin/chrome \
&& ln -sf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone \
&& mkdir -p /usr/share/fonts/chinese/TrueType/
COPY simsun.ttf /usr/share/fonts/chinese/TrueType/simsun.ttf
RUN fc-cache -fv
ENTRYPOINT ["node", "/lib/main.js"]

COPY . .

RUN npm install --production
RUN mv simsun.ttf /usr/local/share/fonts/

ENTRYPOINT ["node", "/lib/main.js"]
RUN npm install --production
10 changes: 5 additions & 5 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ async function run() {
try {
const htmlFile = core.getInput('htmlFile');
const outputFile = core.getInput('outputFile');
const pdfOptions = core.getInput('pdfOptions');

console.log("PWD:",__dirname);
console.log(`Start conver ${htmlFile} to PDF`);
console.log(`Start convert ${htmlFile} to PDF`);

const html5ToPDF = new HTML5ToPDF({
launchOptions:{
executablePath: '/usr/bin/chromium-browser',
args:['--no-sandbox', '--headless', '--disable-gpu']},
executablePath: '/usr/bin/google-chrome-unstable',
args:['--no-sandbox', '--headless', '--disable-gpu']},
pdfOptions: pdfOptions? JSON.parse(pdfOptions) : {},
inputPath: htmlFile,
outputPath: outputFile,

})

await html5ToPDF.start()
Expand Down
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@
"@actions/io": "^1.0.0",
"@actions/tool-cache": "^1.0.0",
"auto-bind": "^2.1.0",
"colors": "^1.3.3",
"commander": "^3.0.0",
"lodash": "^4.17.15",
"puppeteer": "~1.17.0"
"serve-static": "^1.14.1",
"finalhandler": "^1.1.2"
},
"devDependencies": {
"@types/node": "^10.10.4"
"@types/node": "^10.10.4",
"puppeteer": "~1.17.0"
}
}
74 changes: 11 additions & 63 deletions topdf/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
const autoBind = require("auto-bind")
const puppeteer = require("puppeteer")
const map = require("lodash/map")
const pickBy = require("lodash/pickBy")
const Server = require("./server")
const {
readBodyOrFile,
convertPath,
getTemplateFilePath,
convertIncludes,
} = require("./util")

class HTML5ToPDF {
constructor(options) {
Expand All @@ -18,74 +10,30 @@ class HTML5ToPDF {

parseOptions(options) {
const {
inputBody,
inputPath,
outputPath,
templateUrl,
renderDelay,
launchOptions,
include = [],
pdfOptions,
} = options
const legacyOptions = options.options || {}
const pdf = pickBy(
options.pdf || {
landscape: legacyOptions.landscape,
format: legacyOptions.pageSize,
printBackground: legacyOptions.printBackground,
},
)
if (!pdf.path && outputPath) {
pdf.path = convertPath(outputPath)
}
const templatePath = getTemplateFilePath(options)
const body = readBodyOrFile(inputBody, inputPath)

const pdf = pdfOptions
pdf.path = outputPath

return {
body,
pdf,
templatePath,
templateUrl,
launchOptions,
include: convertIncludes(include),
renderDelay,
inputPath
}
}

includeAssets() {
const includePromises = map(this.options.include, ({ type, filePath }) => {
if (type === "js") {
return this.page.addScriptTag({
path: filePath,
})
}
if (type === "css") {
return this.page.addStyleTag({
path: filePath,
})
}
})
includePromises.push(() => {
return this.page.addStyleTag({
path: getTemplateFilePath("pdf.css"),
})
})
includePromises.push(() => {
return this.page.addStyleTag({
path: getTemplateFilePath("highlight.css"),
})
})
return Promise.all(includePromises)
}

async start() {
this.server = new Server(this.options)
await this.server.listen()
this.server = new Server(process.cwd())
this.browser = await puppeteer.launch(this.options.launchOptions)
this.page = await this.browser.newPage()
await this.page.goto(this.server.address(), {
waitUntil: "networkidle2",
const url = "http://localhost:3000/" + this.options.inputPath
await this.page.goto(url, {
waitUntil: "networkidle0",
})
await this.page.setContent(this.options.body)
await this.includeAssets()
if (this.options.renderDelay) {
await this.page.waitFor(this.options.renderDelay)
}
Expand All @@ -101,7 +49,7 @@ class HTML5ToPDF {

async close() {
await this.browser.close()
await this.server.close()
this.server.close()
}
}

Expand Down
90 changes: 11 additions & 79 deletions topdf/server.js
Original file line number Diff line number Diff line change
@@ -1,88 +1,20 @@
const fs = require("fs")
const http = require("http")
const path = require("path")
const { URL, parse } = require("url")
const autoBind = require("auto-bind")
var finalhandler = require('finalhandler')
var http = require('http')
var serveStatic = require('serve-static')

class StaticServer {
constructor({ templatePath }) {
autoBind(this)
this.templatePath = templatePath
this.server = http.createServer(this._handleRequest)
}

address() {
let { address, port } = this.server.address()
if (address === "::") {
address = "localhost"
}
return new URL(`http://${address}:${port}`).toString()
}

listen() {
return new Promise((resolve, reject) => {
this.server.listen(err => {
if (err) {
return reject(err)
}
resolve()
})
})
}

close() {
return new Promise((resolve, reject) => {
this.server.close(err => {
if (err) {
return reject(err)
}
resolve()
})
})
}

_handleRequest(req, res) {
const { pathname } = parse(req.url)
let filePath = path.join(this.templatePath, pathname)
fs.exists(filePath, exists => {
if (!exists) {
res.statusCode = 404
return res.end(`File ${filePath} not found!`)
}

if (fs.statSync(filePath).isDirectory()) {
filePath += "/index.html"
}
class Server {
constructor (path) {
var serve = serveStatic(path, { 'index': ['index.html', 'index.htm'] })

fs.readFile(filePath, (err, data) => {
if (err) {
res.statusCode = 500
res.end(`Error getting the file: ${err}.`)
} else {
res.end(data)
}
})
this.server = http.createServer(function onRequest (req, res) {
serve(req, res, finalhandler(req, res))
})
}
}

class ExistingServer {
constructor({ templateUrl }) {
this.templateUrl = templateUrl
}
async listen() {}
address() {
return new URL(this.templateUrl).toString()
this.server.listen(3000)
}
async close() {}
}

class Server {
constructor({ templatePath, templateUrl }) {
if (templateUrl) {
return new ExistingServer({ templateUrl })
}
return new StaticServer({ templatePath })
close () {
this.server.close()
}
}

Expand Down
50 changes: 0 additions & 50 deletions topdf/util.js

This file was deleted.

0 comments on commit 44d9778

Please sign in to comment.