-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix render to string * reuse render to buffer in tests * move all methods to one file * add more todos * add change set
- Loading branch information
Showing
9 changed files
with
110 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@react-pdf/renderer': patch | ||
--- | ||
|
||
fix `renderToString` method in node js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import fs from 'fs'; | ||
import { Buffer } from 'buffer'; | ||
|
||
import { pdf } from '../index'; | ||
|
||
export const renderToStream = async element => { | ||
const instance = pdf(element); | ||
const stream = await instance.toBuffer(); | ||
return stream; | ||
}; | ||
|
||
export const renderToFile = async (element, filePath, callback) => { | ||
const output = await renderToStream(element); | ||
const stream = fs.createWriteStream(filePath); | ||
|
||
output.pipe(stream); | ||
|
||
return new Promise((resolve, reject) => { | ||
stream.on('finish', () => { | ||
if (callback) callback(output, filePath); | ||
resolve(output); | ||
}); | ||
stream.on('error', reject); | ||
}); | ||
}; | ||
|
||
export const renderToBuffer = element => | ||
renderToStream(element).then( | ||
stream => | ||
new Promise((resolve, reject) => { | ||
const chunks = []; | ||
stream.on('data', chunk => chunks.push(chunk)); | ||
stream.on('end', () => resolve(Buffer.concat(chunks))); | ||
stream.on('error', error => reject(error)); | ||
}), | ||
); | ||
|
||
export const renderToString = element => | ||
renderToBuffer(element).then(buffer => buffer.toString()); |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,128 +1,107 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
/* eslint-disable no-param-reassign */ | ||
|
||
import { Buffer } from 'buffer' | ||
import Canvas from 'canvas' | ||
import * as pdfjs from 'pdfjs-dist/legacy/build/pdf' | ||
import Canvas from 'canvas'; | ||
import * as pdfjs from 'pdfjs-dist/legacy/build/pdf'; | ||
|
||
import { renderToStream } from '..' | ||
import { renderToBuffer } from '..'; | ||
|
||
/** | ||
* copy-pasted code from | ||
* https://github.com/mozilla/pdf.js/blob/master/examples/node/pdf2png/pdf2png.js#L20-L49 | ||
*/ | ||
const NodeCanvasFactory = { | ||
create (width, height) { | ||
const canvas = Canvas.createCanvas(width, height) | ||
const context = canvas.getContext('2d') | ||
create(width, height) { | ||
const canvas = Canvas.createCanvas(width, height); | ||
const context = canvas.getContext('2d'); | ||
return { | ||
canvas, | ||
context | ||
} | ||
context, | ||
}; | ||
}, | ||
|
||
reset (canvasAndContext, width, height) { | ||
canvasAndContext.canvas.width = width | ||
canvasAndContext.canvas.height = height | ||
reset(canvasAndContext, width, height) { | ||
canvasAndContext.canvas.width = width; | ||
canvasAndContext.canvas.height = height; | ||
}, | ||
|
||
destroy (canvasAndContext) { | ||
canvasAndContext.canvas.width = 0 | ||
canvasAndContext.canvas.height = 0 | ||
canvasAndContext.canvas = null | ||
canvasAndContext.context = null | ||
} | ||
} | ||
destroy(canvasAndContext) { | ||
canvasAndContext.canvas.width = 0; | ||
canvasAndContext.canvas.height = 0; | ||
canvasAndContext.canvas = null; | ||
canvasAndContext.context = null; | ||
}, | ||
}; | ||
|
||
async function getCanvas (pagePromise) { | ||
const page = await pagePromise | ||
const viewport = page.getViewport({ scale: 1.0 }) | ||
const canvasFactory = NodeCanvasFactory | ||
async function getCanvas(pagePromise) { | ||
const page = await pagePromise; | ||
const viewport = page.getViewport({ scale: 1.0 }); | ||
const canvasFactory = NodeCanvasFactory; | ||
const { canvas, context } = canvasFactory.create( | ||
viewport.width, | ||
viewport.height | ||
) | ||
viewport.height, | ||
); | ||
const renderContext = { | ||
canvasContext: context, | ||
viewport, | ||
canvasFactory | ||
} | ||
canvasFactory, | ||
}; | ||
|
||
const renderTask = page.render(renderContext) | ||
await renderTask.promise | ||
const renderTask = page.render(renderContext); | ||
await renderTask.promise; | ||
|
||
return canvas | ||
return canvas; | ||
} | ||
|
||
const composeCanvases = (canvases) => { | ||
const composeCanvases = canvases => { | ||
const [maxWidth, maxHeight] = canvases.reduce( | ||
([width, height], canvas) => [ | ||
Math.max(width, canvas.width), | ||
Math.max(height, canvas.height) | ||
Math.max(height, canvas.height), | ||
], | ||
[0, 0] | ||
) | ||
[0, 0], | ||
); | ||
|
||
const resultCanvas = Canvas.createCanvas( | ||
maxWidth, | ||
maxHeight * canvases.length | ||
) | ||
const resultContext = resultCanvas.getContext('2d') | ||
maxHeight * canvases.length, | ||
); | ||
const resultContext = resultCanvas.getContext('2d'); | ||
|
||
canvases.forEach((canvas, index) => { | ||
resultContext.drawImage(canvas, 0, maxHeight * index) | ||
}) | ||
resultContext.drawImage(canvas, 0, maxHeight * index); | ||
}); | ||
|
||
return resultCanvas | ||
} | ||
return resultCanvas; | ||
}; | ||
|
||
/** | ||
* Generates a array with numbers from 0 to length-1 | ||
* @param {number} length — size of array | ||
* @returns {number[]} array | ||
*/ | ||
const range = (length) => Array.from({ length }, (_, index) => index) | ||
const range = length => Array.from({ length }, (_, index) => index); | ||
|
||
/** | ||
* Renders `@react-pdf/renderer` element to buffer | ||
* @param {import('react').ReactElement} element — react element | ||
* @returns {Buffer} raw pdf buffer | ||
*/ | ||
async function renderToBuffer (element) { | ||
const stream = await renderToStream(element) | ||
return new Promise((resolve) => { | ||
const buffers = [] | ||
stream.on('data', (d) => { | ||
buffers.push(d) | ||
}) | ||
stream.on('end', () => { | ||
resolve(Buffer.concat(buffers)) | ||
}) | ||
}) | ||
} | ||
|
||
const renderComponent = async (element) => { | ||
const source = await renderToBuffer(element) | ||
const renderComponent = async element => { | ||
const source = await renderToBuffer(element); | ||
|
||
const document = await pdfjs.getDocument({ | ||
data: source.buffer, | ||
verbosity: 0 | ||
}).promise | ||
verbosity: 0, | ||
}).promise; | ||
|
||
const pages = range(document.numPages).map((pageIndex) => | ||
document.getPage(pageIndex + 1) | ||
) | ||
const pages = range(document.numPages).map(pageIndex => | ||
document.getPage(pageIndex + 1), | ||
); | ||
|
||
if (pages.length === 1) { | ||
return (await getCanvas(pages[0])).toBuffer() | ||
} | ||
return (await getCanvas(pages[0])).toBuffer(); | ||
} | ||
|
||
const canvases = await Promise.all( | ||
pages.map((page) => getCanvas(page)) | ||
) | ||
const pageSnapshots = composeCanvases(canvases) | ||
const canvases = await Promise.all(pages.map(page => getCanvas(page))); | ||
const pageSnapshots = composeCanvases(canvases); | ||
|
||
return pageSnapshots.toBuffer() | ||
} | ||
return pageSnapshots.toBuffer(); | ||
}; | ||
|
||
export default renderComponent | ||
export default renderComponent; |