Skip to content

Instantly share code, notes, and snippets.

@beatwiz
Last active May 3, 2018 11:52
Show Gist options
  • Save beatwiz/c73268b7c70ba894757873ff70ce03f6 to your computer and use it in GitHub Desktop.
Save beatwiz/c73268b7c70ba894757873ff70ce03f6 to your computer and use it in GitHub Desktop.
html2pdfmake vue method
/*
kudos:
https://github.com/ymkins/html2pdfmake/blob/master/html2pdfmake.js
https://github.com/bpampuch/pdfmake/pull/1055
https://github.com/bpampuch/pdfmake/pull/1054
*/
var pdfMake = require('pdfmake/build/pdfmake.js')
var pdfFonts = require('pdfmake/build/vfs_fonts.js')
pdfMake.vfs = pdfFonts.pdfMake.vfs
import logo from '../statics/logo.json'
export default {
/* --- */
methods: {
Export: function () {
var docDefinition = {
pageMargins: [80, 50, 80, 60],
preserveLeadingSpaces: true,
header: {
margin: 0,
columns: [{
absolutePosition: {
x: 0,
y: 0
},
text: '',
width: 300,
alignment: 'left'
},
{
absolutePosition: {
x: 0,
y: 40
},
image: 'logo',
width: 150,
alignment: 'right',
margin: [40, 0]
}
]
},
footer: {
margin: [80, -20],
alignment: 'left',
style: 'small',
columns: [{
width: '100%',
style: 'small',
text: ''
} ]
},
pageBreakBefore: function (currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) {
return currentNode.headlineLevel === 1 && followingNodesOnPage.length === 0
},
content: [{
style: 'p',
alignment: 'justify',
columns: [
this.ParseHtml('<b>Hello world!</b>', false)
]
} ],
styles: {},
images: {
logo: logo.data
}
}
// console.log(docDefinition)
pdfMake.createPdf(docDefinition).download(this.CleanFilename('document.pdf'))
},
CleanFilename (name) {
name = name.replace(/[/\\?%*:|"<>]/g, '-')
return name
},
ParseContainer (cnt, e, p, styles) {
var elements = []
var children = e.childNodes
var i
if (children.length !== 0) {
for (i = 0; i < children.length; i++) p = this.ParseElement(elements, children[i], p, styles)
}
if (elements.length !== 0) {
for (i = 0; i < elements.length; i++) cnt.push(elements[i])
}
return p
},
ComputeStyle (o, styles) {
for (var i = 0; i < styles.length; i++) {
var st = styles[i].trim().toLowerCase().split(':')
if (st.length === 2) {
switch (st[0]) {
case 'font-size':
{
o.fontSize = parseInt(st[1])
break
}
case 'text-align':
{
switch (st[1]) {
case 'right':
o.alignment = 'right'
break
case 'center':
o.alignment = 'center'
break
}
break
}
case 'font-weight':
{
switch (st[1]) {
case 'bold':
o.bold = true
break
}
break
}
case 'text-decoration':
{
switch (st[1]) {
case 'underline':
o.decoration = 'underline'
break
}
break
}
case 'font-style':
{
switch (st[1]) {
case 'italic':
o.italics = true
break
}
break
}
}
}
}
},
ParseElement (cnt, e, p, styles) {
if (!styles) styles = []
if (e.getAttribute) {
var nodeStyle = e.getAttribute('style')
if (nodeStyle) {
var ns = nodeStyle.split(';')
for (var k = 0; k < ns.length; k++) styles.push(ns[k])
}
}
switch (e.nodeName.toLowerCase()) {
case '#text':
{
var t = {
text: e.textContent.replace(/\n/g, '')
}
if (styles) this.ComputeStyle(t, styles)
p.text.push(t)
cnt.push(p)
break
}
case 'b':
case 'strong':
{
this.ParseContainer(cnt, e, p, styles.concat(['font-weight:bold']))
break
}
case 'u':
{
this.ParseContainer(cnt, e, p, styles.concat(['text-decoration:underline']))
break
}
case 'i':
{
this.ParseContainer(cnt, e, p, styles.concat(['font-style:italic']))
break
}
case 'span':
{
this.ParseContainer(cnt, e, p, styles)
break
}
case 'br':
{
p = this.CreateParagraph()
p.text.push({
text: '\n'
})
cnt.push(p)
break
}
case 'table':
{
t = {
table: {
widths: [],
body: []
}
}
var border = e.getAttribute('border')
var isBorder = false
if (border) { if (parseInt(border) === 1) isBorder = true }
if (!isBorder) t.layout = 'noBorders'
this.ParseContainer(t.table.body, e, p, styles)
var widths = e.getAttribute('widths')
if (!widths) {
if (t.table.body.length !== 0) {
if (t.table.body[0].length !== 0) { for (k = 0; k < t.table.body[0].length; k++) t.table.widths.push('*') }
}
} else {
var w = widths.split(',')
for (k = 0; k < w.length; k++) t.table.widths.push(w[k])
}
cnt.push(t)
break
}
case 'tbody':
{
this.ParseContainer(cnt, e, p, styles)
break
}
case 'tr':
{
var row = []
this.ParseContainer(row, e, p, styles)
cnt.push(row)
break
}
case 'td':
{
p = this.CreateParagraph()
var st = {
stack: []
}
st.stack.push(p)
var rspan = e.getAttribute('rowspan')
if (rspan) st.rowSpan = parseInt(rspan)
var cspan = e.getAttribute('colspan')
if (cspan) st.colSpan = parseInt(cspan)
this.ParseContainer(st.stack, e, p, styles)
cnt.push(st)
break
}
case 'div':
case 'li':
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6':
case 'p':
{
p = this.CreateParagraph()
st = {
stack: []
}
//st.stack.push(p)
this.ComputeStyle(st, styles)
this.ParseContainer(st.stack, e, p)
cnt.push(st)
break
}
case 'ul':
var ul = {
margin: [35, 0, 0, 0],
ul: []
}
this.ParseContainer(ul.ul, e, p, styles)
cnt.push(ul)
break
case 'ol':
ul = {
ol: []
}
this.ParseContainer(ul.ol, e, p, styles)
cnt.push(ul)
break
default:
{
console.log('Parsing for node ' + e.nodeName + ' not found')
break
}
}
return p
},
ParseHtml (htmlText, lead = false) {
var cnt = []
var html = new DOMParser().parseFromString(htmlText.replace(/\t/g, '').replace(/\n/g, ''), 'text/html').body.childNodes
var p = this.CreateParagraph()
for (var i = 0; i < html.length; i++) this.ParseElement(cnt, html.item(i), p)
// add indents on first line of paragraphs
if (lead) {
for (var c = 0; c < cnt.length; c++) {
if (Array.isArray(cnt[c].stack[0].text) && cnt[c].stack[0].text.length > 0) {
cnt[c].stack[0].style = 'leading'
}
}
}
return cnt
},
CreateParagraph () {
var p = {
text: []
}
return p
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment