Merge pull request #3 from laurierloi/pdf-support-weasyprint
Pdf support weasyprint
This commit is contained in:
commit
7d61f0e6da
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,6 +22,7 @@ __pycache__
|
|||||||
# Built examples
|
# Built examples
|
||||||
examples/*
|
examples/*
|
||||||
tutorial/*
|
tutorial/*
|
||||||
|
outputs/*
|
||||||
!examples/*.yml
|
!examples/*.yml
|
||||||
!tutorial/*.yml
|
!tutorial/*.yml
|
||||||
!tutorial/*.md
|
!tutorial/*.md
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
# need to install pango > 1.44.0
|
||||||
click
|
click
|
||||||
graphviz
|
graphviz
|
||||||
pillow
|
pillow
|
||||||
@ -5,3 +6,4 @@ pyyaml
|
|||||||
setuptools
|
setuptools
|
||||||
tabulate
|
tabulate
|
||||||
jinja2
|
jinja2
|
||||||
|
weasyprint
|
||||||
|
|||||||
2
src/wireviz/templates/bom.html
generated
2
src/wireviz/templates/bom.html
generated
@ -1,7 +1,7 @@
|
|||||||
<style>
|
<style>
|
||||||
.A4 #bom { /* BOM on top of title block */
|
.A4 #bom { /* BOM on top of title block */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: calc({{ titleblock_rows + 1 }} * 4.25mm);
|
bottom: {{ (titleblock_rows + 1) * 4.25 }}mm;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
src/wireviz/templates/din-6771.html
generated
18
src/wireviz/templates/din-6771.html
generated
@ -38,7 +38,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.A4, .sheetsize_default { /* portrait */
|
.A4 { /* portrait */
|
||||||
width: 180mm;
|
width: 180mm;
|
||||||
height: 277mm;
|
height: 277mm;
|
||||||
}
|
}
|
||||||
@ -62,12 +62,19 @@
|
|||||||
{% set bottom_rows = [bom_rows, titleblock_rows]|max + 1 %}
|
{% set bottom_rows = [bom_rows, titleblock_rows]|max + 1 %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
.A4 #diagram, .A3 #diagram {
|
||||||
|
height: {{ 277 - bottom_rows * 4.25 }}mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.A2 #diagram {
|
||||||
|
height: {{ 400 - bottom_rows * 4.25 }}mm;
|
||||||
|
}
|
||||||
|
|
||||||
#diagram {
|
#diagram {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: calc(100% - {{ bottom_rows }} * 4.25mm);
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
@ -85,14 +92,13 @@
|
|||||||
<style type="text/css" media="print">
|
<style type="text/css" media="print">
|
||||||
|
|
||||||
@page {
|
@page {
|
||||||
size: auto;
|
size: {{ sheetsize }} {{ orientation }};
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: auto-adjust based on portrait (larger margin on left) or landscape (larger margin on top) */
|
|
||||||
#page {
|
#page {
|
||||||
margin: 10mm;
|
margin-top: 10mm;
|
||||||
margin-left: 20mm;
|
margin-left: 15mm; /* TODO: maybe scale this value depending on sheetsize */
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
8
src/wireviz/templates/notes.html
generated
8
src/wireviz/templates/notes.html
generated
@ -2,9 +2,9 @@
|
|||||||
.A4 #notes { /* NOTES on top of BOM */
|
.A4 #notes { /* NOTES on top of BOM */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
{% if show_bom %}
|
{% if show_bom %}
|
||||||
bottom: calc({{ titleblock_rows + bom_rows + 2 }} * 4.25mm);
|
bottom: {{ (titleblock_rows + bom_rows + 2) * 4.25 }}mm;
|
||||||
{% else %}
|
{% else %}
|
||||||
bottom: calc({{ titleblock_rows + 1 }} * 4.25mm);
|
bottom: {{ (titleblock_rows + 1) * 4.25 }}mm;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
@ -12,11 +12,11 @@
|
|||||||
.A3 #notes, .A2 #notes { /* NOTES on top of title block */
|
.A3 #notes, .A2 #notes { /* NOTES on top of title block */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
{% if notes_on_right %}
|
{% if notes_on_right %}
|
||||||
bottom: calc({{ titleblock_rows + 1 }} * 4.25mm);
|
bottom: {{ (titleblock_rows + 1) * 4.25 }}mm;
|
||||||
right: 0;
|
right: 0;
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if show_bom %}
|
{% if show_bom %}
|
||||||
bottom: calc({{ bom_rows + 1 }} * 4.25mm);
|
bottom: {{ (bom_rows + 1) * 4.25 }}mm;
|
||||||
{% else %}
|
{% else %}
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
11
src/wireviz/templates/titleblock.html
generated
11
src/wireviz/templates/titleblock.html
generated
@ -1,13 +1,8 @@
|
|||||||
<style>
|
<style>
|
||||||
#titleblock {
|
#titleblock {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0mm;
|
bottom: 0;
|
||||||
right: -0mm;
|
right: 0;
|
||||||
}
|
|
||||||
|
|
||||||
#titleblock {
|
|
||||||
width: 180mm;
|
|
||||||
height: calc({{ titleblock_rows }} * 4.25mm));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#titleblock table, th, td {
|
#titleblock table, th, td {
|
||||||
@ -108,7 +103,7 @@
|
|||||||
|
|
||||||
<!-- START OF TEMPLATE --!>
|
<!-- START OF TEMPLATE --!>
|
||||||
<div id="titleblock">
|
<div id="titleblock">
|
||||||
<table id="titleblock">
|
<table>
|
||||||
<tr> <!-- ROW 1 --!>
|
<tr> <!-- ROW 1 --!>
|
||||||
<!-- REVISIONS Column 1 to 4 --!>
|
<!-- REVISIONS Column 1 to 4 --!>
|
||||||
{{ revision(1) }}
|
{{ revision(1) }}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ groups = {
|
|||||||
|
|
||||||
input_extensions = [".yml"]
|
input_extensions = [".yml"]
|
||||||
extensions_not_containing_graphviz_output = [".gv", ".bom.tsv"]
|
extensions_not_containing_graphviz_output = [".gv", ".bom.tsv"]
|
||||||
extensions_containing_graphviz_output = [".png", ".svg", ".html"]
|
extensions_containing_graphviz_output = [".png", ".svg", ".html", ".pdf"]
|
||||||
generated_extensions = (
|
generated_extensions = (
|
||||||
extensions_not_containing_graphviz_output + extensions_containing_graphviz_output
|
extensions_not_containing_graphviz_output + extensions_containing_graphviz_output
|
||||||
)
|
)
|
||||||
@ -68,7 +68,7 @@ def build_generated(groupkeys):
|
|||||||
try:
|
try:
|
||||||
res = cli([
|
res = cli([
|
||||||
"--formats",
|
"--formats",
|
||||||
"ghpst",
|
"ghpstPb",
|
||||||
str(yaml_file),
|
str(yaml_file),
|
||||||
"--prepend",
|
"--prepend",
|
||||||
yaml_file.parent / "metadata.yml"
|
yaml_file.parent / "metadata.yml"
|
||||||
|
|||||||
@ -14,6 +14,7 @@ from wireviz import APP_NAME, __version__
|
|||||||
from wireviz.wv_bom import bom_list
|
from wireviz.wv_bom import bom_list
|
||||||
from wireviz.wv_utils import bom2tsv
|
from wireviz.wv_utils import bom2tsv
|
||||||
from wireviz.wv_harness_quantity import HarnessQuantity
|
from wireviz.wv_harness_quantity import HarnessQuantity
|
||||||
|
from wireviz.wv_output import generate_pdf_output
|
||||||
|
|
||||||
format_codes = {
|
format_codes = {
|
||||||
"c": "csv",
|
"c": "csv",
|
||||||
@ -126,9 +127,11 @@ def cli(files, formats, prepend, output_dir, output_name, version, use_qty_multi
|
|||||||
harness = None
|
harness = None
|
||||||
shared_bom = {}
|
shared_bom = {}
|
||||||
sheet_current = 1
|
sheet_current = 1
|
||||||
|
output_names = []
|
||||||
# run WireVIz on each input file
|
# run WireVIz on each input file
|
||||||
for _file in files:
|
for _file in files:
|
||||||
_output_name = _file.stem if not output_name else output_name
|
_output_name = _file.stem if not output_name else output_name
|
||||||
|
output_names.append(_output_dir / _output_name)
|
||||||
|
|
||||||
print("Input file: ", _file)
|
print("Input file: ", _file)
|
||||||
print(
|
print(
|
||||||
@ -155,6 +158,9 @@ def cli(files, formats, prepend, output_dir, output_name, version, use_qty_multi
|
|||||||
)
|
)
|
||||||
shared_bom = ret["shared_bom"]
|
shared_bom = ret["shared_bom"]
|
||||||
|
|
||||||
|
if 'pdf' in output_formats and 'html' in output_formats and len(output_names) > 1:
|
||||||
|
generate_pdf_output(output_names)
|
||||||
|
|
||||||
# TODO: move shared bom generation to a method?
|
# TODO: move shared bom generation to a method?
|
||||||
if "shared_bom" in output_formats:
|
if "shared_bom" in output_formats:
|
||||||
shared_bom_file = (_output_dir / "shared_bom").with_suffix(".tsv")
|
shared_bom_file = (_output_dir / "shared_bom").with_suffix(".tsv")
|
||||||
|
|||||||
@ -30,7 +30,7 @@ from wireviz.wv_graphviz import (
|
|||||||
parse_arrow_str,
|
parse_arrow_str,
|
||||||
set_dot_basics,
|
set_dot_basics,
|
||||||
)
|
)
|
||||||
from wireviz.wv_output import embed_svg_images_file, generate_html_output
|
from wireviz.wv_output import embed_svg_images_file, generate_html_output, generate_pdf_output
|
||||||
from wireviz.wv_utils import bom2tsv
|
from wireviz.wv_utils import bom2tsv
|
||||||
|
|
||||||
|
|
||||||
@ -394,8 +394,7 @@ class Harness:
|
|||||||
generate_html_output(filename, bomlist, self.metadata, self.options)
|
generate_html_output(filename, bomlist, self.metadata, self.options)
|
||||||
# PDF output
|
# PDF output
|
||||||
if "pdf" in fmt:
|
if "pdf" in fmt:
|
||||||
# TODO: implement PDF output
|
generate_pdf_output(filename)
|
||||||
print("PDF output is not yet supported")
|
|
||||||
# delete SVG if not needed
|
# delete SVG if not needed
|
||||||
if "html" in fmt and not "svg" in fmt:
|
if "html" in fmt and not "svg" in fmt:
|
||||||
# SVG file was just needed to generate HTML
|
# SVG file was just needed to generate HTML
|
||||||
|
|||||||
@ -3,7 +3,10 @@
|
|||||||
import base64
|
import base64
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Union
|
from typing import Dict, List, Union
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from weasyprint import HTML
|
||||||
|
|
||||||
import wireviz # for doing wireviz.__file__
|
import wireviz # for doing wireviz.__file__
|
||||||
from wireviz.wv_dataclasses import Metadata, Options
|
from wireviz.wv_dataclasses import Metadata, Options
|
||||||
@ -56,6 +59,28 @@ def embed_svg_images_file(
|
|||||||
filename_out.replace(filename_in)
|
filename_out.replace(filename_in)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_pdf_output(
|
||||||
|
filename_list: List[Path],
|
||||||
|
options: Dict=None,
|
||||||
|
):
|
||||||
|
'''Generate a pdf output, options are ignored for now, expect the formatting
|
||||||
|
to be done within the html files
|
||||||
|
'''
|
||||||
|
if isinstance(filename_list, Path):
|
||||||
|
filename_list = [filename_list]
|
||||||
|
output_path = filename_list[0].with_suffix('.pdf')
|
||||||
|
else:
|
||||||
|
output_dir = filename_list[0].parent
|
||||||
|
output_path = (output_dir / output_dir.name).with_suffix('.pdf')
|
||||||
|
|
||||||
|
filepath_list = [f.with_suffix('.html') for f in filename_list]
|
||||||
|
|
||||||
|
print(f'Generating pdf output: {output_path}')
|
||||||
|
files_html = [HTML(path) for path in filepath_list]
|
||||||
|
documents = [f.render() for f in files_html]
|
||||||
|
all_pages = [p for doc in documents for p in doc.pages]
|
||||||
|
documents[0].copy(all_pages).write_pdf(output_path)
|
||||||
|
|
||||||
|
|
||||||
def generate_html_output(
|
def generate_html_output(
|
||||||
filename: Path,
|
filename: Path,
|
||||||
@ -117,7 +142,8 @@ def generate_html_output(
|
|||||||
added_metadata = {
|
added_metadata = {
|
||||||
"revisions": [],
|
"revisions": [],
|
||||||
"authors": [],
|
"authors": [],
|
||||||
"sheetsize": "sheetsize_default",
|
"sheetsize": "A4",
|
||||||
|
"orientation": "portrait",
|
||||||
}
|
}
|
||||||
if metadata:
|
if metadata:
|
||||||
for item, contents in metadata.items():
|
for item, contents in metadata.items():
|
||||||
@ -132,9 +158,9 @@ def generate_html_output(
|
|||||||
elif item == "pn":
|
elif item == "pn":
|
||||||
added_metadata[item] = f'{contents}-{metadata.get("sheet_name")}'
|
added_metadata[item] = f'{contents}-{metadata.get("sheet_name")}'
|
||||||
elif item == "template":
|
elif item == "template":
|
||||||
added_metadata["sheetsize"] = contents.get(
|
added_metadata["sheetsize"] = contents.get("sheetsize", "A4")
|
||||||
"sheetsize", "sheetsize_default"
|
if added_metadata["sheetsize"] in ["A2", "A3"]:
|
||||||
)
|
added_metadata["orientation"] = "landscape"
|
||||||
else:
|
else:
|
||||||
added_metadata[item] = contents
|
added_metadata[item] = contents
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user