Exemplo n.º 1
1
    def print_certidao(self, request, diligencias):
        """
        :param diligencias:
        :return:
        """
        from weasyprint import HTML, CSS
        from django.conf import settings
        from app.models import Diligencia
        from django.utils import datetime_safe


        modelo_html = ''
        for i in range(len(diligencias)):
            if i == 0:                                          #primeira certidão # '<meta charset="utf-8" />'
                modelo_html += '<html>' \
                               '<head>' \
                               '<meta charset="utf-8" />' \
                               '<base href="http://ofjusapp.pythonanywhere.com/">'\
                               '</head>' \
                               '<body>' \
                               '<div style="float: none;">' \
                               '<div>'
                modelo_html += diligencias[i].documento
                modelo_html += '</div>'
            else:                                               #certidões intermediarias
                modelo_html += '<div style="page-break-before:always;">'
                modelo_html += diligencias[i].documento
                modelo_html += '</div>'
        modelo_html += '</div></body></html>'
        pdf_html = HTML(string=modelo_html)
        main_doc = pdf_html.render()
        pdf_file = main_doc.write_pdf()
        diligencias.update(imprimir=False)
        #pdf_file = HTML('http://weasyprint.org/').write_pdf('/tmp/weasyprint-website.pdf')
        return pdf_file  # returns the response.
Exemplo n.º 2
0
 def form_valid(self, form):
     self.post_data = self.request.POST
     if 'download' in self.post_data:
         html = self.render_to_response(self.get_context_data(form=form))
         f = open(os.path.join(
             os.path.dirname(__file__), './static/payslip/css/payslip.css'))
         html = HTML(string=html.render().content)
         pdf = html.write_pdf(stylesheets=[CSS(string=f.read())])
         f.close()
         resp = HttpResponse(pdf, content_type='application/pdf')
         resp['Content-Disposition'] = \
             u'attachment; filename="{}_{}.pdf"'.format(
                 self.date_start.year, self.date_start.month)
         return resp
     return self.render_to_response(self.get_context_data(form=form))
Exemplo n.º 3
0
    def serve_pdf(self, request):
        # Render html content through html template with context
        template = get_template(settings.PDF_TEMPLATE)
        context = {"invoice": self}

        html = template.render(context)

        # Write PDF to file
        document_html = HTML(string=html, base_url=request.build_absolute_uri())
        document = document_html.render()
        if len(document.pages) > 1:
            for page in document.pages[1:]:
                str(page)
            pdf = document.write_pdf()
        else:
            pdf = document.write_pdf()
        # response = HttpResponse(html)
        response = HttpResponse(pdf, content_type="application/pdf")
        response["Content-Disposition"] = 'filename="Invoice {0} | Invoice {0}.pdf"'.format(self.id)
        return response
Exemplo n.º 4
0
    def print_avisos(self, request, mandados):
        """
        :param mandados:
        :return:
        """
        from weasyprint import HTML, CSS
        from django.conf import settings
        from app.models import Atendimento, Oficial
        from django.utils import datetime_safe

        oj = Oficial.objects.get(usuario=request.user)
        atendimentos = Atendimento.objects.filter(oficial=oj, data__gt=datetime_safe.date.today())
        av = Modelo_Documento.objects.get(nome='AVISO')

        modelo_html = ''
        for i in range(len(mandados)):
            if i == 0:                                          #primeiro aviso # '<meta charset="utf-8" />'
                modelo_html += '<html>' \
                               '<head>' \
                               '<meta charset="utf-8" />' \
                               '</head>' \
                               '<body>' \
                               '<div style="float: none;">' \
                               '<div>'
                c = template.Context({'mandado':mandados[0], 'atendimentos':atendimentos})#.last()})
                t = template.Template(av.modelo)
                modelo_html += t.render(c)
                modelo_html += '</div>'
            else:                                               #avisos intermediarios
                modelo_html += '<div style="page-break-before:always;">'
                c = template.Context({'mandado':mandados[i], 'atendimentos':atendimentos})#.last()})
                t = template.Template(av.modelo)
                modelo_html += t.render(c)
                modelo_html += '</div>'
        modelo_html += '</div></body></html>'
        #print(modelo_html)
        pdf_html = HTML(string=modelo_html)
        main_doc = pdf_html.render()
        pdf_file = main_doc.write_pdf()
        #pdf_file = HTML('http://weasyprint.org/').write_pdf('/tmp/weasyprint-website.pdf')
        return pdf_file  # returns the response.
Exemplo n.º 5
0
def generate_pdf(body):
    html = HTML(string=body)
    main_doc = html.render()
    pdf = main_doc.write_pdf()
    return pdf
Exemplo n.º 6
0
def grabPRCY(fileAddr):
	from grab import Grab

	def clearStr( string ):
		if type(string) != type(None):
			return string.replace('\n','').replace('\t','').replace('\r','')

	g = Grab()

	g.go('https://id.pr-cy.ru/signup/login/')
			
	g.doc.set_input('login_email','*****@*****.**') 
	g.doc.set_input('password','biksileev')
	g.doc.submit()
	output = open('Finished.txt', 'w')

	j = 1

	phant = webdriver.PhantomJS()

	for string in fileinput.input(fileAddr):

		customerList = string.split('	')

		customerList[2] = clearStr(customerList[2])

		phant.get('https://a.pr-cy.ru/' + customerList[1])

		time.sleep(60)

		g.go('https://a.pr-cy.ru/' + customerList[1])

		newList = g.css_list('.is')

		print(len(newList))

		i = 0

		f = open('audit/' + customerList[1] + '.html','w')
		f.write('''<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8" />
			<link rel='stylesheet' href="style.css">
		</head>
		<body>
			<div id="head">
				<img src="biksileev.jpg"/>
				<h1>Технический аудит сайта http://''' + customerList[1] + '''</h1>
				<p>Для чёткого понимания текущего технического состояния сайта http://''' + customerList[1] + '''
был проведён полный технический аудит, результаты которого представлены ниже в виде таблицы.</p></div>''')
		f.write('<div>')
		f.write('<table>')
		f.write('<thead><tr><td colspan="2">Технический аудит</td></tr></thead>')
		f.write('<tbody>')
		f.write('<tr><td>Критерий</td><td>Текущее состояние</td></tr>')

		for name in newList:
			if True: #not('Обратные ссылки' in name.cssselect('.info-test')[0].text) or not('Аналитика' in name.cssselect('.info-test')[0].text):
				if len(name.cssselect('.info-test')) > 0:
					print(name.cssselect('.info-test')[0].text)
					if (('Описание страницы' or 'Скриншот сайта на смартфоне') in name.cssselect('.info-test')[0].text):
						f.write('</table></div><div class="pageBreak"><table>')
						f.write('<tr ><td class="left">')
					else:
						f.write('<tr><td class="left">')
					f.write(name.cssselect('.info-test')[0].text)
					f.write('</td>')
					f.write(' ')
					if len(name.cssselect('.content-test')) > 0:
						if (len(clearStr(name.cssselect('.content-test')[0].text)) > 0):
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							if (len(name.cssselect('.content-test')[0].cssselect('a')) > 0): 
								f.write(clearStr(name.cssselect('.content-test')[0].text) + clearStr(name.cssselect('.content-test')[0].cssselect('a')[0].text))
							else:
								f.write(clearStr(name.cssselect('.content-test')[0].text))
							f.write('</td>')
						elif (len(name.cssselect('.content-test')[0].cssselect('.iphone .iphone-screen img')) > 0):
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							f.write('<img src="http://' + name.cssselect('.content-test')[0].cssselect('.iphone .iphone-screen img')[0].get('src')[2:] + '">')
							f.write('</td>')
						elif(('Facebook' in name.cssselect('.info-test')[0].text) or ('ВКонтакте' in name.cssselect('.info-test')[0].text) or ('Google+' in name.cssselect('.info-test')[0].text) or ('Twitter' in name.cssselect('.info-test')[0].text)):
							if(name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
								f.write('Ссылка на страницу найдена.')
								f.write('</td>')
							elif(name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
								f.write('Ссылка на страницу не найдена.')
								f.write('</td>')
						elif ((len(name.cssselect('.content-test')[0].cssselect('a')) > 0)):
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							f.write(clearStr(name.cssselect('.content-test')[0].cssselect('a')[0].text))
							f.write('</td>')
						elif (len(name.cssselect('.content-test')[0].cssselect('p')) > 0):
							newList2 = name.cssselect('.content-test')[0].cssselect('p')
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							for paragraph in newList2:
								f.write(clearStr(paragraph.text))
								f.write('<br>')
							f.write('</td>')
						elif (len(name.cssselect('.content-test')[0].cssselect('.progress-info .progress-info')) > 0):
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							f.write(clearStr(name.cssselect('.content-test')[0].cssselect('.progress-info .progress-info')[0].text))
							f.write('</td>')
						elif (len(name.cssselect('.content-test')[0].cssselect('.progress-info')) > 0):
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							f.write(clearStr(name.cssselect('.content-test')[0].cssselect('.progress-info')[0].text))
							f.write('</td>')
						elif (len(name.cssselect('.content-test')[0].cssselect('span')) > 0) or ('Системы статистики' in name.cssselect('.info-test')[0].text):
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							newList2 = name.cssselect('.content-test')[0].cssselect('span')
							for analytics in newList2:
								f.write(clearStr(analytics.text))
								f.write('<br>')
							f.write('</td>')
					elif (len(name.cssselect('.info-test')) > 0):
						if('Местоположение сервера' in name.cssselect('.info-test')[0].text):
							if (name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
							elif (name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right unsuccess">')
							else:
								f.write('<td class="right">')
							f.write(name.cssselect('.content-test img')[0].get('alt').split(' ')[2])
							f.write('</td>')
						elif('Favicon' in name.cssselect('.info-test')[0].text):
							if(name.cssselect('.check-test')[0].get('test-status') == 'success'):
								f.write('<td class="right success">')
								f.write('Отлично, у сайта есть Favicon.')
								f.write('</td>')
							elif(name.cssselect('.check-test')[0].get('test-status') == 'fail'):
								f.write('<td class="right success">')
								f.write('Отлично, у сайта есть Favicon.')
								f.write('</td>')
			i += 1
			'''f.write('<td>')
			newList3 = name.cssselect('.description p')
			for paragraph in newList3:
			f.write(paragraph.text)'''
		f.write('</tbody>')
		f.write('</table>')
		f.write('''<p> Резолюция
Сайт частично оптимизирован.</p>
		</body>
		</html>
			''')
		f.close()
		file = HTML(filename="audit/" + customerList[1] + ".html")
		file.render().write_pdf(target="audit/" + customerList[1] + ".pdf")
		#file.render('file://' + os.getcwd() + '/audit/' + customerList[1] + '.html', 'audit/' + customerList[1] + '.pdf')
		subject = customerList[0] + ' - подготовили аудит вашего сайта: ' + customerList[1]
		message = customerList[0] + """, добрый день!

Причина нашего обращения к Вам не случайна.

Специалистами студии Дмитрия Биксилеева в течение марта месяца проводился выборочный аудит сайтов компаний работающих в сфере услуг для бизнеса. В том числе был проведен краткий аудит Вашего сайта %s

Нашими SEO-специалистами выявлены достаточно серьезные ошибки на сайте, мешающие его продвижению в поисковых системах и снижающие удобство пользования вашим сайтом для ваших потенциальных клиентов (см. приложение «Экспресс аудит сайта»). Как правило, данные ошибки не заметны на первый взгляд, но об их наличии убедительно свидетельствует низкий КПД сайта.

Наверное, и Вы сами, как ответственный и экономный хозяин, периодически задаетесь вопросом:

Почему сайт, в который вложено столько интеллектуальных и финансовых ресурсов не оправдывает свое существование?
Почему клиенты заходят на сайт, но не совершают покупок?
Почему Ваши конкуренты уводят клиентов?

Мы дадим ответы на все интересующие Вас вопросы и с удовольствием поделимся самыми свежими и самыми необходимыми в XXI веке знаниями по интернет-маркетингу. В случае Вашей заинтересованности, сделаем полный базовый, технический и юзабилити аудит сайта, предложим реальные сроки и способы устранения недостатков и выведем Ваш сайт на лидирующие позиции в поисковиках по самым высоко конверсионным запросам.

Мы не предлагаем Вам услуги с непредсказуемым или неубедительным результатом. Мы предлагаем взрывной рост Вашему Интернет-бизнесу!

Помогая Вам в бизнесе, мы становимся своеобразным хуком в интернет-продажах, Вашим директором по маркетингу, полностью выстраивающим маркетинг и систему продаж.

С уважением к Вам и Вашему бизнесу, Бубновский Михаил
Директор по развитию компании Студия Дмитрия Биксилеева

----------------------------------------------------------
Тел.: +7(343)298-03-54
Сот. Тел.: +7 (922)1554515
E-mail: [email protected]
skype: ottepel_1
www.biksileev.ru""" % customerList[1]
		#sendMail(customerList[2], subject, message, 'audit/' + customerList[1] + '.pdf')
		customerList.append('Отправлено')
		output.write('	'.join(customerList))
		output.write('\n')
		text1.delete('1.0', str(len('	'.join(customerList) + '\n') + 1) + '.0') 
		text1.insert(str(j) + '.0', '	'.join(customerList) + '\n')
		text1.update()
	output.close()
	phant.quit()
Exemplo n.º 7
0
documents = []

# loop through each page of the tutorial calling the already declared functions
# on them
while True:
    parent = get_page(page)
    get_next_page(parent)
    html = remove_unwanted(parent)

    # create an html instance
    html_instance = HTML(string=html)

    # call weasyprint's render method on the html instance to obtain in
    # return an instance of the Document class which is stored in the doc object
    doc = html_instance.render()

    # append every consecutive doc object to the documents list
    # that was created earlier.
    documents.append(doc)

    # print the url of the current page to the console, this is solely
    # for debugging and has no effect on the script
    print(page)

    # let the loop sleep for about 3secs before sending another request to
    # to the server, this helps to prevent overloading the server from our end
    time.sleep(3)

    # end loop when you get to your desired end-page
    if page == 'https://www.w3schools.com/python/python_mysql_getstarted.asp':
Exemplo n.º 8
0
def constructSvg(procSerial):
    """
  Construct a SVG image out of a processed, dashboard builder serialized state.

  Args:
    procSerial: A list representing the dashboard state to be exported. Each item
      in the list is a dictonary with a `itemType` field, detailing what sort of
      item is to be drawn.

      The item types that are drawn so far are 'ChartItem's, 'TitleItem's and
      'CommentItem's.

  Returns:
    A svg string representing the image.
  """
    svgHeight, svgWidth = _getSize(procSerial)
    draw = svgwrite.Drawing(size=(svgWidth, svgHeight))
    drawHead, drawTail = draw.tostring()[0:-6], draw.tostring()[-6:]
    drawBody = ""
    for dashItem in procSerial:
        position = {
            k: v * GRID_SIZE
            for k, v in dashItem['position'].iteritems()
        }
        w, h, x, y = position['width'], position['height'], position[
            'left'], position['top']
        g = svgwrite.container.Group()
        g.translate(x, ty=y)
        if dashItem['itemType'] in JS_ITEMS:
            for item in dashItem['items']:
                t, attrs = item['type'], item['attr']
                if t == 'rect':
                    svg, attrs = _svgRect(draw, attrs)
                elif t == 'circle':
                    svg, attrs = _svgCirc(draw, attrs)
                elif t == 'path':
                    svg, attrs = _svgPath(draw, attrs)
                elif t == 'text':
                    svg, attrs = _svgText(draw, attrs)
                g.add(svg)

        elif dashItem['itemType'] == 'TitleItem':
            titleSvg, attrs = _svgText(
                draw, {
                    'x': 0,
                    'y': 0,
                    'text': dashItem['textContent'],
                    'lineHeight': dashItem.get('lineHeight', 10),
                    'font-size': '1.35em',
                    'font-family': 'helvetica',
                    'font-weight': 'bold'
                })
            g.add(titleSvg)

        elif dashItem['itemType'] == 'CommentItem':
            bgSvg, attrs = _svgRect(
                draw, {
                    'x': COMMENT_PADDING,
                    'y': COMMENT_PADDING,
                    'width': w - COMMENT_PADDING,
                    'height': h - COMMENT_PADDING,
                    'fill': '#fff8b6',
                    'stroke': '#eae1a0',
                    'stroke-width': 1
                })
            g.add(bgSvg)

            authorSvg, attrs = _svgText(
                draw, {
                    'x':
                    COMMENT_PADDING + AUTHOR_PADDING,
                    'y':
                    COMMENT_PADDING + 2 * AUTHOR_PADDING,
                    'text':
                    dashItem['author'],
                    'lineHeight':
                    dashItem['lineHeight'],
                    'font-weight':
                    600,
                    'font-size':
                    '1em',
                    'fill':
                    '#8c8c8c',
                    'clip':
                    'rect(10,10,{width},{height})'.format(
                        width=w - COMMENT_PADDING, height=h - COMMENT_PADDING),
                    'font-family':
                    'helvetica'
                })
            g.add(authorSvg)

            textSvg, attrs = _svgText(
                draw, {
                    'x': COMMENT_PADDING + AUTHOR_PADDING,
                    'y': COMMENT_PADDING + AUTHOR_PADDING + AUTHOR_HEIGHT,
                    'text': dashItem['textContent'],
                    'lineHeight': dashItem['lineHeight'],
                    'font-weight': 'normal',
                    'font-size': '1em',
                    'font-family': 'helvetica'
                })
            g.add(textSvg)

        elif dashItem['itemType'] == 'PivotTableItem':
            from weasyprint import HTML, CSS
            dashItem['html'] = dashItem['html']\
              .replace('align="right"', 'class="alignright"')\
              .replace('align="center"', 'class="aligncenter"')
            html = HTML(string=dashItem['html'])

            wpx, hpx = '{width}px'.format(width=w), '{height}px'.format(
                height=h)
            css = CSS(string="""
        @page {
          margin: 0;
          padding: 0;
          size: %s %s;
        }
        table, th, td, tr {
          border: 1px solid black;
          border-collapse: collapse;
          border-spacing: 0;
          padding: 0;
          margin: 0;
          font-weight: normal;
          background-color: white;
        }
        table {
          width: %s;
          height: %s;
        }
        .alignright {
          text-align: right;
        }
        .aligncenter {
          text-align: center;
        }
      """ % (wpx, hpx, wpx, hpx))

            page = html.render(stylesheets=[css]).pages[0]
            with tmpfile() as tmp:
                import cairocffi as cairo
                surface = cairo.SVGSurface(tmp, x + page.width,
                                           y + page.height)
                page.paint(cairo.Context(surface), left_x=x, top_y=y)
                surface.finish()

                tmp.seek(0)
                for line in tmp:
                    if re.match(r'<(?:xml|(/)?svg).*>', line) is None:
                        drawBody += line
                drawBody = drawBody.rstrip()

        if dashItem['itemType'] != "PivotTableItem":
            drawBody += g.tostring()
    return drawHead + drawBody + drawTail
Exemplo n.º 9
0
def generate_pdf(body):
    html = HTML(string=body)
    main_doc = html.render()
    pdf = main_doc.write_pdf()
    return pdf
Exemplo n.º 10
0
def asiento_contable_con_comprobante_generar_tirilla(asiento_contable_id: int):
    asiento_contable = AsientoContable.objects.get(pk=asiento_contable_id)
    comprobante_contable = asiento_contable.tipo_comprobante_bancario_empresa
    empresa = comprobante_contable.empresa
    context = {
        "nota":
        asiento_contable.nota,
        "fecha":
        asiento_contable.fecha,
        "concepto":
        asiento_contable.concepto,
        "nro_comprobante":
        asiento_contable.nro_comprobante,
        "tercero_nombre":
        asiento_contable.tercero.full_name_proxy
        if asiento_contable.tercero else None,
        "usuario":
        asiento_contable.usuario.get_full_name()
        if asiento_contable.usuario else None,
        "nit_empresa":
        empresa.nit if empresa else None,
        "nombre_empresa":
        empresa.nombre if empresa else None,
        "pais":
        comprobante_contable.pais_emision if comprobante_contable else None,
        "ciudad":
        comprobante_contable.ciudad_emision if comprobante_contable else None,
        "telefono":
        comprobante_contable.telefono_emision
        if comprobante_contable else None,
        "direccion":
        comprobante_contable.direccion_emision
        if comprobante_contable else None,
        "fecha_autorizacion":
        comprobante_contable.fecha_autorizacion
        if comprobante_contable else None,
        "rango_superior_numeracion":
        comprobante_contable.rango_superior_numeracion
        if comprobante_contable else None,
        "rango_inferior_numeracion":
        comprobante_contable.rango_inferior_numeracion
        if comprobante_contable else None,
        "numero_autorizacion":
        comprobante_contable.numero_autorizacion
        if comprobante_contable else None,
        "descripcion_comprobante":
        comprobante_contable.tipo_comprobante.descripcion
        if comprobante_contable else None,
        "codigo_comprobante":
        comprobante_contable.tipo_comprobante.codigo_comprobante,
        "valor":
        asiento_contable.total_credito
    }
    html_get_template = get_template(
        'comprobantes_contables/comprobante_contable.html').render(context)
    html = HTML(string=html_get_template)
    width = '80mm'
    height = '10cm'
    size = 'size: %s %s' % (width, height)
    margin = 'margin: 0.8cm 0.8cm 0.8cm 0.8cm'

    css_string = '@page {text-align: justify; font-family: Arial;font-size: 0.6rem;%s;%s}' % (
        size, margin)
    main_doc = html.render(stylesheets=[CSS(string=css_string)])
    return main_doc
Exemplo n.º 11
0
def constructSvg(procSerial):
  """
  Construct a SVG image out of a processed, dashboard builder serialized state.

  Args:
    procSerial: A list representing the dashboard state to be exported. Each item
      in the list is a dictonary with a `itemType` field, detailing what sort of
      item is to be drawn.

      The item types that are drawn so far are 'ChartItem's, 'TitleItem's and
      'CommentItem's.

  Returns:
    A svg string representing the image.
  """
  svgHeight, svgWidth = _getSize(procSerial)
  draw = svgwrite.Drawing(size=(svgWidth, svgHeight))
  drawHead, drawTail  = draw.tostring()[0:-6], draw.tostring()[-6:]
  drawBody = ""
  for dashItem in procSerial:
    position = {k: v * GRID_SIZE for k, v in dashItem['position'].iteritems()}
    w, h, x, y = position['width'], position['height'], position['left'], position['top']
    g = svgwrite.container.Group()
    g.translate(x, ty=y)
    if dashItem['itemType'] in JS_ITEMS:
      for item in dashItem['items']:
        t, attrs = item['type'], item['attr']
        if   t == 'rect':
          svg, attrs = _svgRect(draw, attrs)
        elif t == 'circle':
          svg, attrs = _svgCirc(draw, attrs)
        elif t == 'path':
          svg, attrs = _svgPath(draw, attrs)
        elif t == 'text':
          svg, attrs = _svgText(draw, attrs)
        g.add(svg)

    elif dashItem['itemType'] == 'TitleItem':
      titleSvg, attrs = _svgText(draw,
          { 'x':           0
          , 'y':           0
          , 'text':        dashItem['textContent']
          , 'lineHeight':  dashItem.get('lineHeight', 10)
          , 'font-size':   '1.35em'
          , 'font-family': 'helvetica'
          , 'font-weight': 'bold' })
      g.add(titleSvg)

    elif dashItem['itemType'] == 'CommentItem':
      bgSvg, attrs = _svgRect(draw,
          { 'x':            COMMENT_PADDING
          , 'y':            COMMENT_PADDING
          , 'width':        w - COMMENT_PADDING
          , 'height':       h - COMMENT_PADDING
          , 'fill':         '#fff8b6'
          , 'stroke':       '#eae1a0'
          , 'stroke-width': 1 })
      g.add(bgSvg)

      authorSvg, attrs = _svgText(draw,
          { 'x':           COMMENT_PADDING + AUTHOR_PADDING
          , 'y':           COMMENT_PADDING + 2 * AUTHOR_PADDING
          , 'text':        dashItem['author']
          , 'lineHeight':  dashItem['lineHeight']
          , 'font-weight': 600
          , 'font-size':   '1em'
          , 'fill':        '#8c8c8c'
          , 'clip':        'rect(10,10,{width},{height})'.format(
                             width  = w - COMMENT_PADDING
                           , height = h - COMMENT_PADDING)
          , 'font-family': 'helvetica' })
      g.add(authorSvg)

      textSvg, attrs = _svgText(draw,
          { 'x':           COMMENT_PADDING + AUTHOR_PADDING
          , 'y':           COMMENT_PADDING + AUTHOR_PADDING + AUTHOR_HEIGHT
          , 'text':        dashItem['textContent']
          , 'lineHeight':  dashItem['lineHeight']
          , 'font-weight': 'normal'
          , 'font-size':   '1em'
          , 'font-family': 'helvetica' })
      g.add(textSvg)

    elif dashItem['itemType'] == 'PivotTableItem':
      from weasyprint import HTML, CSS
      dashItem['html'] = dashItem['html']\
        .replace('align="right"', 'class="alignright"')\
        .replace('align="center"', 'class="aligncenter"')
      html = HTML(string=dashItem['html'])

      wpx, hpx = '{width}px'.format(width = w), '{height}px'.format(height = h)
      css = CSS(string="""
        @page {
          margin: 0;
          padding: 0;
          size: %s %s;
        }
        table, th, td, tr {
          border: 1px solid black;
          border-collapse: collapse;
          border-spacing: 0;
          padding: 0;
          margin: 0;
          font-weight: normal;
          background-color: white;
        }
        table {
          width: %s;
          height: %s;
        }
        .alignright {
          text-align: right;
        }
        .aligncenter {
          text-align: center;
        }
      """ % (wpx, hpx, wpx, hpx))

      page = html.render(stylesheets=[css]).pages[0]
      with tmpfile() as tmp:
        import cairocffi as cairo
        surface = cairo.SVGSurface(tmp, x + page.width, y + page.height)
        page.paint(cairo.Context(surface), left_x=x, top_y=y)
        surface.finish()

        tmp.seek(0)
        for line in tmp:
          if re.match(r'<(?:xml|(/)?svg).*>', line) is None:
            drawBody += line
        drawBody = drawBody.rstrip()

    if dashItem['itemType'] != "PivotTableItem":
      drawBody += g.tostring()
  return drawHead + drawBody + drawTail