- Using peerDependencies for pdfkit
- adding callback for element drawing.
- support color from color books
- must use my forked pdfkit
- support customized getComputedStyle
- Add getComputedStyleCallback
import SVGtoPDF from "svg-to-pdfkit";
import { load } from "color-books";
const getColor = (bookName, colorName: string) {
const book = load(bookName);
if (book.records[colorName]) {
return {
name: colorName,
colorSpace: book.colorSpace,
components: book.records[colorName].components,
isSpot: book.isSpot
};
}
};
// <path d="..." fill="COLOR_BOOK(PANTONE+ CMYK Coated/PANTONE P 24-8 C)"></path>
const parseColorCallback = (color) => {
const temp = color.match(/^COLOR_BOOK\((.+)\/(.+)\)$/);
if (temp) {
const [bookName, colorName] = temp.slice(1);
return getColor(bookName, colorName);
}
};
const draw = (doc, svg, { left, top, width, height }) => {
doc.save();
try {
SVGtoPDF(doc, svg, left, top, {
width,
height,
parseColorCallback
});
} finally {
doc.restore();
}
};
fs = require 'fs'
PDFDocument = require 'pdfkit'
SVGtoPDF = require 'svg-to-pdfkit'
open = require 'opn'
cheerio = require 'cheerio'
css = require 'css'
doc = new PDFDocument autoFirstPage: false
###
<svg>
<defs>
<style>
.cls-1 {
fill: red;
}
.cls-2 {
stroke: yellow;
}
</style>
</defs>
<rect class="cls-1 cls-2" x="0" y="0" width="100" height="100" />
</svg>
###
svgContent = fs.readFileSync 'has-css.svg', 'utf8'
$ = cheerio.load svgContent, xmlMode: true
styles = reduce.call $('svg defs style').contents(), (sum, curr) ->
if curr.type is 'text'
sum += curr.data + '\n'
sum
, ''
parsed = css.parse(styles)
cssProps = parsed.stylesheet.rules.reduce (propsBySelector, rule) ->
if rule.type is 'rule'
props = rule.declarations.reduce (sum, decor) ->
sum[decor.property] = decor.value
sum
, {}
for s in rule.selectors
propsBySelector[s] = props
propsBySelector
, {}
doc.pipe fs.createWriteStream 'output.pdf'
doc.addPage { size: [512, 512], margin: 0 }
getComputedStyleCallback = (node) ->
if node.getAttribute('class')
classNames = node.getAttribute('class').split(/\s/)
styles = classNames.reduce((sum, name) ->
name = '.' + name
if cssProps[name]
sum = { sum..., cssProps[name]... }
sum
, {})
styles
SVGtoPDF doc, svgContent, 0, 0, { width: 200, height: 200, getComputedStyleCallback }
doc.end();
Insert SVG into a PDF document created with PDFKit.
SVGtoPDF(doc, svg, x, y, options);
If you prefer, you can add the function to the PDFDocument prototype:
PDFDocument.prototype.addSVG = function(svg, x, y, options) {
return SVGtoPDF(this, svg, x, y, options), this;
};
And then simply call:
doc.addSVG(svg, x, y, options);
doc [PDFDocument] = the PDF document created with PDFKit
svg [SVGElement or string] = the SVG object or XML code
x, y [number] = the position where the SVG will be added
options [Object] = >
- width, height [number] = initial viewport, by default it's the page dimensions
- preserveAspectRatio [string] = override alignment of the SVG content inside its viewport
- useCSS [boolean] = use the CSS styles computed by the browser (for SVGElement only)
- fontCallback [function] = function called to get the fonts, see source code
- imageCallback [function] = same as above for the images (for Node.js)
- warningCallback [function] = function called when there is a warning
- assumePt [boolean] = assume that units are PDF points instead of SVG pixels
- precision [number] = precision factor for approximative calculations (default = 3)
https://alafr.github.io/SVG-to-PDFKit/examples/demo.htm
https://alafr.github.io/SVG-to-PDFKit/examples/options.htm
- shapes: rect, circle, path, ellipse, line, polyline, polygon
- special elements: use, nested svg
- text elements: text, tspan, textPath
- text attributes: x, y, dx, dy, rotate, text-anchor, textLength, word-spacing, letter-spacing, font-size
- styling: with attributes only
- colors: fill, stroke & color (rgb, rgba, hex, string), fill-opacity, stroke-opacity & opacity
- units: all standard units
- transformations: transform, viewBox & preserveAspectRatio attributes
- clip paths & masks
- images
- fonts
- gradients
- patterns
- links (#18)
- filters
- text attributes: text-decoration, font-variant, writing-mode, unicode-bidi
- foreignObject (#37)
- other things I don't even know they exist
- Use an updated PDFKit version (≥0.8.1): see here how to build it, or use the prebuilt file in the examples folder.
- There are bugs, please send issues and/or pull requests.
- PDFKit, the JavaScript PDF generation library for Node and the browser.
- For inserting SVG graphics into a PDFKit document there is also svgkit.
- For the opposite conversion, from PDF to SVG, you can use Mozilla's PDF.js.