UNPKG

augmented-reality-pdf

Version:

A module to prepare PDF documents for AR. It automatically inserts a QR code and an image target of choice on each page of the document.

111 lines (100 loc) 5.47 kB
const fs = require('fs'); const fsc = require("fs-cheerio"); const cheerio = require('cheerio'); const sharp = require('sharp'); const path = require('path'); const pdf = require('html-pdf'); const QRCode = require('qrcode'); const htmlToPdf = require('html-to-pdf'); const dockerCLI = require('docker-cli-js'); const wkhtmltopdf = require('wkhtmltopdf'); const cmd=require('node-cmd'); const DockerOptions = dockerCLI.Options; const Docker = dockerCLI.Docker; var letters = getLetterArray(); /* Converts a PDF document to HTML format using Docker and inserts a QR code and an image target on all pages Takes an options object as input with the following properties: input: Relative path of input. Must have .pdf extension if useDocker is set to true. Must have .html extension if useDocker is set to false. output: Relative path of output file. Defaults to './annotated.pdf'. target: Relative path of Image Target width: Width of image target/QR code in pixels height: Height of image target/QR code in pixel text: Text to automatically generate QR code from qr: Relative path of QR code image if not using automatically generated QR code from text top: Offset from top of page of image target/QR code in pixels left: Offset from left of page of image target/QR code in pixels pages: Number of pages in the PDF document to place target/QR code on useImageTarget: Whether to embed an image or not. Defaults to true. useQRCode: Whether to embed a QR code or not. Defaults to true. useDocker: Whether to use Docker or not. If set to false, input has to be a html file. If set to true, input has to be a pdf file. dockerOptions: Optional Docker Options, see https://www.npmjs.com/package/docker-cli-js */ async function insertQRAndMarker(options) { var useDocker = options.useDocker !== undefined ? options.useDocker : false; var result = useDocker ? await insertQRAndMarkerDocker(options) : await insertQRAndMarkerNoDocker(options); } async function insertQRAndMarkerDocker(options) { const dockerOptions = options.dockerOptions || new DockerOptions(); const docker = new Docker(dockerOptions); var input = path.parse(options.input).ext === '.pdf' ? options.input : 'sample.pdf'; var pdf_to_html = await convertToHTML(input, docker); await insertQRAndMarkerBase(__dirname + '/' + path.parse(input).name + '.html', options.target || 'target.jpg', options.qr || 'generated_qr.png', options.text || 'Hey', options.width || 50, options.height || 50, options.top || 1020, options.left || 0, options.pages || 100, options.output || 'annotated.pdf', options.useQRCode || true, options.useImageTarget || true); } async function insertQRAndMarkerNoDocker(options) { var input = path.parse(options.input).ext === '.html' ? options.input : 'sample.html'; await insertQRAndMarkerBase(__dirname + '/' + input, options.target || 'target.jpg', options.qr || 'generated_qr.png', options.text || 'Hey', options.width || 50, options.height || 50, options.top || 1020, options.left || 0, options.pages || 100, options.output || 'annotated.pdf', options.useQRCode || true, options.useImageTarget || true); } async function insertQRAndMarkerBase(input, target, qr, text, width, height, top, left, pages, output, useQRCode, useImageTarget) { var $ = cheerio.load(fs.readFileSync(input)); var QRCODE = await QRCode.toFile('generated_qr.png', text); var resized_target = await resizeImage(__dirname + '/' + target, __dirname + '/target_resized.png', width, height); var resized_qr = await resizeImage(__dirname + '/' + qr, __dirname + '/qr_resized.png', width, height); var target_html = '<img src="target_resized.png" style="z-index:1000 !important; position: absolute; left: ' + new String(left) + 'px; top: ' + new String(top-height) + 'px"/>'; var qr_html = '<img src="qr_resized.png" style="z-index:1000 !important; position: absolute; left: ' + new String(left+width) + 'px; top: ' + new String(top-height) + 'px"/>'; var augment = (useImageTarget ? target_html : '') + (useQRCode ? qr_html : ''); for (var i = 0; i < pages; i++) { $('div[data-page-no=' + new String (i) + ']').append(augment); } for (var i = 0; i < letters.length; i++) { $('div[data-page-no=' + letters[i] + ']').append(augment); } await fsc.writeFile(__dirname + '/annotated.html', $); await htmlToPDF(input, output); } async function convertToHTML(input, docker) { var data = await docker.command('run --rm -v ' + __dirname + '/:/pdf bwits/pdf2htmlex pdf2htmlEX --zoom 1.3 --proof 1 ' + input); } async function resizeImage(input, output, x, y) { var resized = await sharp(input).resize(x, y) .toFile(output); } async function htmlToPDF(input, output) { var stream = await cmd.run('wkhtmltopdf annotated.html ' + output); await fs.unlinkSync(input); setTimeout(async function(){ await fs.unlinkSync(__dirname + '/target_resized.png'); await fs.unlinkSync(__dirname + '/qr_resized.png'); await fs.unlinkSync(__dirname + '/generated_qr.png'); await fs.unlinkSync(__dirname + '/annotated.html'); },30000); return stream; } function getLetterArray() { var letters=[], letter_first = 'a', letter_last = 'z'; for (var letter = letter_first.charCodeAt(0); letter<=letter_last.charCodeAt(0); letter++) letters.push(String.fromCharCode(letter)); return letters; } module.exports = { insertQRAndMarker: insertQRAndMarker, htmlToPDF: htmlToPDF }