svg-paper

The world's most maintainable way to create paper-printable documents 🖨💘

TOC
Workflows
You can print beautiful and maintainable paper documents by following steps:
- Design the document with Adobe XD, Figma, or something
- Export it as SVG
- Embed SVG into your HTML and fix it with svg-paper
- That's it 💥
To learn more please see this doc 📝
Installation
CDN
You can get built assets from jsDelivr.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/svg-paper@x.x.x/dist/svg-paper.min.css">
<script src="https://cdn.jsdelivr.net/npm/svg-paper@x.x.x/dist/svg-paper.min.js"></script>
npm
Of course you can install via npm.
$ npm install svg-paper
Basic usage
You can replace or adjust SVG contents in HTML easily with svg-paper like following.
import SvgPaper from 'svg-paper'
const paper = new SvgPaper()
paper
.replace('%placeholder1%', 'Actual value 1')
.adjustText('#selector1', 1000)
.adjustText('#selector2', 800, 'middle')
.adjustText('#selector3', 800, 'end')
.adjustTetxarea('#selector4', 600, 300)
.adjustTextarea('#selector5',
600,
300,
1.2,
0.5,
0.5,
false
)
.apply()
To beautify preview screen, you should add only 3 lines to your HTML 👍
<head>
...
<link rel="stylesheet" href="svg-paper.min.css">
<style>@page { size: A4 }</style>
</head>
<body class="A4">
<svg>...</svg>
</body>
Just load svg-paper.min.css
(or svg-paper.css
), in <head>
set @page size, and set the class of <body>
to specify page size.
Available page sizes are:
A3
A3 landscape
A4
A4 landscape
A5
A5 landscape
letter
letter landscape
legal
legal landscape
To learn more about usage please see this doc or some test codes.
Tips
Hiding content before placeholders are replaced
svg-paper replaces placeholders and adjust text/textarea after DOM loaded, so the content before replaced and adjusted will be shown on the screen for a moment 🤔
This problem is very easy to solve just by adding some "blinder" layer on the content and disappear it after .apply()
👍
<body>
<div id="blinder" style="width:100vw; height:100vh; background-color:#ccc"></div>
<svg>...</svg>
</body>
paper.apply()
document.querySelector('#blinder').style.display = 'none'
With non Node.js back-end
Even if your back-end isn't Node.js, of course you can use svg-paper 👍
The most easy ways is just passing replacements and text/textarea adjustment parameters to front-end as JSON string.
e.g. PHP and Twig
public function paper(YourModel $model, YourPaperDefinition $paper)
{
return $this->render('paper.html.twig', [
'svg' => $paper->getSvg(),
'replacements' => $paper->getReplacements($model),
'textAdjustments' => $paper->getTextAdjustments(),
'textAreaAdjustments' => $paper->getTextAreaAdjustments(),
]);
}
class YourPaperDefinition
{
public function getSvg()
{
return file_get_contents('/path/to/paper.svg');
}
public function getReplacements(YourModel $model): array
{
return [
'%placeholder1%' => 'Actual value 1',
];
}
public function getTextAdjustments(): array
{
return [
'#selector1' => [1000],
'#selector2' => [800, 'middle'],
'#selector3' => [800, 'end'],
];
}
public function getTextareaAdjustments(): array
{
return [
'#selector2' => [600, 300],
];
}
}
{# paper.html.twig #}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="svg-paper.min.css">
<style>@page { size: A4 }</style>
</head>
<body class="A4">
{{ svg|raw }}
<div data-replacements="{{ replacements|json_encode }}"></div>
<div data-text-adjustments="{{ textAdjustments|json_encode }}"></div>
<div data-textarea-adjustments="{{ textAdjustments|json_encode }}"></div>
<script src="svg-paper.min.js"></script>
<script src="your-script.js"></script>
</body>
</html>
const replacements = $('[data-replacements]').data('replacements')
const textAdjustments = $('[data-adjustments]').data('text-adjustments')
const textareaAdjustments = $('[data-adjustments]').data('textarea-adjustments')
const paper = new SvgPaper()
for (let [search, replacement] of Object.entries(replacements)) {
paper.replace(search, replacement)
}
for (let [selector, args] of Object.entries(textAdjustments)) {
paper.adjustText(selector, ...args)
}
for (let [selector, args] of Object.entries(textareaAdjustments)) {
paper.adjustTextarea(selector, ...args)
}
paper.apply()
PDF generation
You can easily print to PDF directly by using electron-pdf.
$ npm install --global electron-pdf
$ electron-pdf your-document.html your-document.pdf
Enjoy! ✨