We try to convert incoming SVG data into a PDF output that is stored on our server. The processing is restricted to JavaScript and is preferrably done on a Deno server (or node.js). Our approach is to send SVG data via POST request to our Deno server and use svg2pdf.js (extends jsPDF) to generate and store the resulting PDF document. In this post we describe our approach and share our experience for all of you working on a similar project. Moreover, we ask for the appraisal of yours that already have dealt with similar issues.
Running svg2pdf.js in the browser works remarkebly well and the conversion of SVG to PDF is accurate. Yet, running the library in the Deno environment differs slightly from the web browser and causes a few problems. The library is designed to run in the browser and relies on the DOM. Nevertheless, there are JavaScript implementations of the DOM Web API which may mitigate this problem. After importing svg2pdf.js on a Deno instance, it seems that the DOM is needed to (1) parse the SVG document and (2) calculate dimensions of objects.
In how far is running svg2pdf.js on a Deno server promising to successfully built a PDF?
Minimal example repository for reproducing the error: GitHub: proto-deno-svg2pdf
(1) Parsing the SVG document: Document Object Model for Deno
svg2pdf.js relies on a DOM to parse the SVG document tree. While Deno does not provide a native DOM API, though the module Deno DOM implements the DOM Web API. (Further DOM parsers are: jsdom, /zuisong/happy-dom-deno or LinkeDOM).
Deno DOM needs few added functions and attributes to parse a SVG document (e.g., Document:createElementNS(), Element:setAttributeNS()). So far, traversing elements and constructing the document tree seems to work fine. A few missing pieces seem to be easily extensible within the classes.
The rendering on the other hand seems more difficult to implement on a server…
(2) Calculating dimensions of SVG objects
svg2pdf.js additionally relies on the Canvas API to render objects. When executed in the browser the calculation and the subsequent rendering works very well.
Challenge: Dependencies to Canvas API and SVGGraphicsElement
In the Deno environment we have two blocking issues identified so far which raise the doubt in our current approach. Because svg2pdf.js relies on Canvas API as well as SVGGraphicsElement:
TextMeasure.prototype.canvasTextMeasure() relies on canvas.getContext('2d') which is not implemented in Deno DOM. Moreover, TextMeasure.prototype.svgTextMeasure() relies on SVGGraphicsElement.getBBox() which is not implemented in Deno DOM. That is why the conversion is stuck at the point of calculating the dimensions of SVG objects:
TypeError: textNode.getBBox is not a function
at TextMeasure.svgTextMeasure (file:///home/christian/projects/svg2pdf.js_deno/dist/svg2pdf.es.js:594:25)
Other popular DOM parser like jsdom seem to omit the implementation of getBBox() as well. From this perspective it seems that there might be more problems down this path. Thats why we are in doubt about this approach.
My questions:
-
For peer developers: Has anyone experiences with implementing svg2pdf.js on a Deno or Node.js server?
-
For module maintainers: Svg2pdf.js depends on DOM and Canvas API. In how far are DOM parser such as Deno DOM or jsdom adequate tools for calculating dimensions of SVG elements printing them on a PDF?
For anyone interested in this challenge, please have a look at the minimum example repository linked above.
Thank you in advance for sharing your thoughts with me!