Add basic options and metadata (#214)
This commit is contained in:
parent
e212fc9058
commit
92354e6852
@ -3,6 +3,12 @@
|
|||||||
## Main sections
|
## Main sections
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
metadata: # dictionary of meta-information describing the harness
|
||||||
|
<key> : <value> # any number of key value pairs (see below)
|
||||||
|
...
|
||||||
|
options: # dictionary of common attributes for the whole harness
|
||||||
|
<str> : <value> # optional harness attributes (see below)
|
||||||
|
...
|
||||||
connectors: # dictionary of all used connectors
|
connectors: # dictionary of all used connectors
|
||||||
<str> : # unique connector designator/name
|
<str> : # unique connector designator/name
|
||||||
... # connector attributes (see below)
|
... # connector attributes (see below)
|
||||||
@ -31,6 +37,55 @@ additional_bom_items: # custom items to add to BOM
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Metadata entries
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Meta-information describing the harness
|
||||||
|
|
||||||
|
# Each key/value pair replaces all key references in
|
||||||
|
# the HTML output template with the belonging value.
|
||||||
|
# Typical keys are 'title', 'description', and 'notes',
|
||||||
|
# but any key is accepted. Unused keys are ignored.
|
||||||
|
<key> : <value> # Any valid YAML syntax is accepted
|
||||||
|
# If no value is specified for 'title', then the
|
||||||
|
# output filename without extension is used.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Common attributes for the whole harness.
|
||||||
|
# All entries are optional and have default values.
|
||||||
|
|
||||||
|
# Background color of diagram and HTML output
|
||||||
|
bgcolor: <color> # Default = 'WH'
|
||||||
|
|
||||||
|
# Background color of other diagram elements
|
||||||
|
bgcolor_node: <color> # Default = 'WH'
|
||||||
|
bgcolor_connector: <color> # Default = bgcolor_node
|
||||||
|
bgcolor_cable: <color> # Default = bgcolor_node
|
||||||
|
bgcolor_bundle: <color> # Default = bgcolor_cable
|
||||||
|
|
||||||
|
# How to display colors as text in the diagram
|
||||||
|
# 'full' : Lowercase full color name
|
||||||
|
# 'FULL' : Uppercase full color name
|
||||||
|
# 'hex' : Lowercase hexadecimal values
|
||||||
|
# 'HEX' : Uppercase hexadecimal values
|
||||||
|
# 'short': Lowercase short color name
|
||||||
|
# 'SHORT': Uppercase short color name
|
||||||
|
# 'ger' : Lowercase short German color name
|
||||||
|
# 'GER' : Uppercase short German color name
|
||||||
|
color_mode: <str> # Default = 'SHORT'
|
||||||
|
|
||||||
|
# Fontname to use in diagram and HTML output
|
||||||
|
fontname: <str> # Default = 'arial'
|
||||||
|
|
||||||
|
# If True, show only a BOM entry reference together with basic info
|
||||||
|
# about additional components inside the diagram node (connector/cable box).
|
||||||
|
# If False, show all info about additional components inside the diagram node.
|
||||||
|
mini_bom_mode: <bool> # Default = True
|
||||||
|
```
|
||||||
|
|
||||||
## Connector attributes
|
## Connector attributes
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from typing import Optional, List, Tuple, Union
|
from typing import Dict, List, Optional, Tuple, Union
|
||||||
from dataclasses import dataclass, field, InitVar
|
from dataclasses import dataclass, field, InitVar
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ ConnectorMultiplier = PlainText # = Literal['pincount', 'populated']
|
|||||||
CableMultiplier = PlainText # = Literal['wirecount', 'terminations', 'length', 'total_length']
|
CableMultiplier = PlainText # = Literal['wirecount', 'terminations', 'length', 'total_length']
|
||||||
ImageScale = PlainText # = Literal['false', 'true', 'width', 'height', 'both']
|
ImageScale = PlainText # = Literal['false', 'true', 'width', 'height', 'both']
|
||||||
Color = PlainText # Two-letter color name = Literal[wv_colors._color_hex.keys()]
|
Color = PlainText # Two-letter color name = Literal[wv_colors._color_hex.keys()]
|
||||||
|
ColorMode = PlainText # = Literal['full', 'FULL', 'hex', 'HEX', 'short', 'SHORT', 'ger', 'GER']
|
||||||
ColorScheme = PlainText # Color scheme name = Literal[wv_colors.COLOR_CODES.keys()]
|
ColorScheme = PlainText # Color scheme name = Literal[wv_colors.COLOR_CODES.keys()]
|
||||||
|
|
||||||
# Type combinations
|
# Type combinations
|
||||||
@ -30,6 +31,33 @@ Wire = Union[int, PlainText] # Wire number or Literal['s'] for shield
|
|||||||
NoneOrMorePinIndices = Union[PinIndex, Tuple[PinIndex, ...], None] # None, one, or a tuple of zero-based pin indices
|
NoneOrMorePinIndices = Union[PinIndex, Tuple[PinIndex, ...], None] # None, one, or a tuple of zero-based pin indices
|
||||||
OneOrMoreWires = Union[Wire, Tuple[Wire, ...]] # One or a tuple of wires
|
OneOrMoreWires = Union[Wire, Tuple[Wire, ...]] # One or a tuple of wires
|
||||||
|
|
||||||
|
# Metadata can contain whatever is needed by the HTML generation/template.
|
||||||
|
MetadataKeys = PlainText # Literal['title', 'description', 'notes', ...]
|
||||||
|
class Metadata(dict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Options:
|
||||||
|
fontname: PlainText = 'arial'
|
||||||
|
bgcolor: Color = 'WH'
|
||||||
|
bgcolor_node: Optional[Color] = 'WH'
|
||||||
|
bgcolor_connector: Optional[Color] = None
|
||||||
|
bgcolor_cable: Optional[Color] = None
|
||||||
|
bgcolor_bundle: Optional[Color] = None
|
||||||
|
color_mode: ColorMode = 'SHORT'
|
||||||
|
mini_bom_mode: bool = True
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if not self.bgcolor_node:
|
||||||
|
self.bgcolor_node = self.bgcolor
|
||||||
|
if not self.bgcolor_connector:
|
||||||
|
self.bgcolor_connector = self.bgcolor_node
|
||||||
|
if not self.bgcolor_cable:
|
||||||
|
self.bgcolor_cable = self.bgcolor_node
|
||||||
|
if not self.bgcolor_bundle:
|
||||||
|
self.bgcolor_bundle = self.bgcolor_cable
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Image:
|
class Image:
|
||||||
|
|||||||
@ -4,13 +4,14 @@
|
|||||||
from graphviz import Graph
|
from graphviz import Graph
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from itertools import zip_longest
|
from itertools import zip_longest
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from wireviz import wv_colors, __version__, APP_NAME, APP_URL
|
from wireviz import wv_colors, __version__, APP_NAME, APP_URL
|
||||||
from wireviz.DataClasses import Connector, Cable
|
from wireviz.DataClasses import Metadata, Options, Connector, Cable
|
||||||
from wireviz.wv_colors import get_color_hex
|
from wireviz.wv_colors import get_color_hex, translate_color
|
||||||
from wireviz.wv_gv_html import nested_html_table, html_colorbar, html_image, \
|
from wireviz.wv_gv_html import nested_html_table, html_colorbar, html_image, \
|
||||||
html_caption, remove_links, html_line_breaks
|
html_caption, remove_links, html_line_breaks
|
||||||
from wireviz.wv_bom import manufacturer_info_field, component_table_entry, \
|
from wireviz.wv_bom import manufacturer_info_field, component_table_entry, \
|
||||||
@ -20,11 +21,12 @@ from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, flatten2d, \
|
|||||||
open_file_read, open_file_write
|
open_file_read, open_file_write
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
class Harness:
|
class Harness:
|
||||||
|
metadata: Metadata
|
||||||
|
options: Options
|
||||||
|
|
||||||
def __init__(self):
|
def __post_init__(self):
|
||||||
self.color_mode = 'SHORT'
|
|
||||||
self.mini_bom_mode = True
|
|
||||||
self.connectors = {}
|
self.connectors = {}
|
||||||
self.cables = {}
|
self.cables = {}
|
||||||
self._bom = [] # Internal Cache for generated bom
|
self._bom = [] # Internal Cache for generated bom
|
||||||
@ -91,18 +93,19 @@ class Harness:
|
|||||||
dot = Graph()
|
dot = Graph()
|
||||||
dot.body.append(f'// Graph generated by {APP_NAME} {__version__}')
|
dot.body.append(f'// Graph generated by {APP_NAME} {__version__}')
|
||||||
dot.body.append(f'// {APP_URL}')
|
dot.body.append(f'// {APP_URL}')
|
||||||
font = 'arial'
|
|
||||||
dot.attr('graph', rankdir='LR',
|
dot.attr('graph', rankdir='LR',
|
||||||
ranksep='2',
|
ranksep='2',
|
||||||
bgcolor='white',
|
bgcolor=wv_colors.translate_color(self.options.bgcolor, "HEX"),
|
||||||
nodesep='0.33',
|
nodesep='0.33',
|
||||||
fontname=font)
|
fontname=self.options.fontname)
|
||||||
dot.attr('node', shape='record',
|
dot.attr('node',
|
||||||
|
shape='none',
|
||||||
|
width='0', height='0', margin='0', # Actual size of the node is entirely determined by the label.
|
||||||
style='filled',
|
style='filled',
|
||||||
fillcolor='white',
|
fillcolor=wv_colors.translate_color(self.options.bgcolor_node, "HEX"),
|
||||||
fontname=font)
|
fontname=self.options.fontname)
|
||||||
dot.attr('edge', style='bold',
|
dot.attr('edge', style='bold',
|
||||||
fontname=font)
|
fontname=self.options.fontname)
|
||||||
|
|
||||||
# prepare ports on connectors depending on which side they will connect
|
# prepare ports on connectors depending on which side they will connect
|
||||||
for _, cable in self.cables.items():
|
for _, cable in self.cables.items():
|
||||||
@ -126,7 +129,8 @@ class Harness:
|
|||||||
[html_line_breaks(connector.type),
|
[html_line_breaks(connector.type),
|
||||||
html_line_breaks(connector.subtype),
|
html_line_breaks(connector.subtype),
|
||||||
f'{connector.pincount}-pin' if connector.show_pincount else None,
|
f'{connector.pincount}-pin' if connector.show_pincount else None,
|
||||||
connector.color, html_colorbar(connector.color)],
|
translate_color(connector.color, self.options.color_mode) if connector.color else None,
|
||||||
|
html_colorbar(connector.color)],
|
||||||
'<!-- connector table -->' if connector.style != 'simple' else None,
|
'<!-- connector table -->' if connector.style != 'simple' else None,
|
||||||
[html_image(connector.image)],
|
[html_image(connector.image)],
|
||||||
[html_caption(connector.image)]]
|
[html_caption(connector.image)]]
|
||||||
@ -148,7 +152,7 @@ class Harness:
|
|||||||
pinhtml.append(f' <td>{pinlabel}</td>')
|
pinhtml.append(f' <td>{pinlabel}</td>')
|
||||||
if connector.pincolors:
|
if connector.pincolors:
|
||||||
if pincolor in wv_colors._color_hex.keys():
|
if pincolor in wv_colors._color_hex.keys():
|
||||||
pinhtml.append(f' <td sides="tbl">{pincolor}</td>')
|
pinhtml.append(f' <td sides="tbl">{translate_color(pincolor, self.options.color_mode)}</td>')
|
||||||
pinhtml.append( ' <td sides="tbr">')
|
pinhtml.append( ' <td sides="tbr">')
|
||||||
pinhtml.append( ' <table border="0" cellborder="1"><tr>')
|
pinhtml.append( ' <table border="0" cellborder="1"><tr>')
|
||||||
pinhtml.append(f' <td bgcolor="{wv_colors.translate_color(pincolor, "HEX")}" width="8" height="8" fixedsize="true"></td>')
|
pinhtml.append(f' <td bgcolor="{wv_colors.translate_color(pincolor, "HEX")}" width="8" height="8" fixedsize="true"></td>')
|
||||||
@ -166,7 +170,8 @@ class Harness:
|
|||||||
html = [row.replace('<!-- connector table -->', '\n'.join(pinhtml)) for row in html]
|
html = [row.replace('<!-- connector table -->', '\n'.join(pinhtml)) for row in html]
|
||||||
|
|
||||||
html = '\n'.join(html)
|
html = '\n'.join(html)
|
||||||
dot.node(connector.name, label=f'<\n{html}\n>', shape='none', margin='0', style='filled', fillcolor='white')
|
dot.node(connector.name, label=f'<\n{html}\n>', shape='box', style='filled',
|
||||||
|
fillcolor=translate_color(self.options.bgcolor_connector, "HEX"))
|
||||||
|
|
||||||
if len(connector.loops) > 0:
|
if len(connector.loops) > 0:
|
||||||
dot.attr('edge', color='#000000:#ffffff:#000000')
|
dot.attr('edge', color='#000000:#ffffff:#000000')
|
||||||
@ -211,7 +216,8 @@ class Harness:
|
|||||||
f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else None,
|
f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else None,
|
||||||
'+ S' if cable.shield else None,
|
'+ S' if cable.shield else None,
|
||||||
f'{cable.length} {cable.length_unit}' if cable.length > 0 else None,
|
f'{cable.length} {cable.length_unit}' if cable.length > 0 else None,
|
||||||
cable.color, html_colorbar(cable.color)],
|
translate_color(cable.color, self.options.color_mode) if cable.color else None,
|
||||||
|
html_colorbar(cable.color)],
|
||||||
'<!-- wire table -->',
|
'<!-- wire table -->',
|
||||||
[html_image(cable.image)],
|
[html_image(cable.image)],
|
||||||
[html_caption(cable.image)]]
|
[html_caption(cable.image)]]
|
||||||
@ -232,7 +238,7 @@ class Harness:
|
|||||||
wireinfo = []
|
wireinfo = []
|
||||||
if cable.show_wirenumbers:
|
if cable.show_wirenumbers:
|
||||||
wireinfo.append(str(i))
|
wireinfo.append(str(i))
|
||||||
colorstr = wv_colors.translate_color(connection_color, self.color_mode)
|
colorstr = wv_colors.translate_color(connection_color, self.options.color_mode)
|
||||||
if colorstr:
|
if colorstr:
|
||||||
wireinfo.append(colorstr)
|
wireinfo.append(colorstr)
|
||||||
if cable.wirelabels:
|
if cable.wirelabels:
|
||||||
@ -332,9 +338,11 @@ class Harness:
|
|||||||
to_string = ''
|
to_string = ''
|
||||||
html = [row.replace(f'<!-- {connection.via_port}_out -->', to_string) for row in html]
|
html = [row.replace(f'<!-- {connection.via_port}_out -->', to_string) for row in html]
|
||||||
|
|
||||||
|
style, bgcolor = ('filled,dashed', self.options.bgcolor_bundle) if cable.category == 'bundle' else \
|
||||||
|
('filled', self.options.bgcolor_cable)
|
||||||
html = '\n'.join(html)
|
html = '\n'.join(html)
|
||||||
dot.node(cable.name, label=f'<\n{html}\n>', shape='box',
|
dot.node(cable.name, label=f'<\n{html}\n>', shape='box',
|
||||||
style='filled,dashed' if cable.category == 'bundle' else '', margin='0', fillcolor='white')
|
style=style, fillcolor=translate_color(bgcolor, "HEX"))
|
||||||
|
|
||||||
return dot
|
return dot
|
||||||
|
|
||||||
@ -368,7 +376,7 @@ class Harness:
|
|||||||
with open_file_write(f'{filename}.bom.tsv') as file:
|
with open_file_write(f'{filename}.bom.tsv') as file:
|
||||||
file.write(tuplelist2tsv(bomlist))
|
file.write(tuplelist2tsv(bomlist))
|
||||||
# HTML output
|
# HTML output
|
||||||
generate_html_output(filename, bomlist)
|
generate_html_output(filename, bomlist, self.metadata, self.options)
|
||||||
|
|
||||||
def bom(self):
|
def bom(self):
|
||||||
if not self._bom:
|
if not self._bom:
|
||||||
|
|||||||
@ -13,6 +13,7 @@ if __name__ == '__main__':
|
|||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
|
||||||
from wireviz import __version__
|
from wireviz import __version__
|
||||||
|
from wireviz.DataClasses import Metadata, Options
|
||||||
from wireviz.Harness import Harness
|
from wireviz.Harness import Harness
|
||||||
from wireviz.wv_helper import expand, open_file_read
|
from wireviz.wv_helper import expand, open_file_read
|
||||||
|
|
||||||
@ -34,7 +35,12 @@ def parse(yaml_input: str, file_out: (str, Path) = None, return_types: (None, st
|
|||||||
|
|
||||||
yaml_data = yaml.safe_load(yaml_input)
|
yaml_data = yaml.safe_load(yaml_input)
|
||||||
|
|
||||||
harness = Harness()
|
harness = Harness(
|
||||||
|
metadata = Metadata(**yaml_data.get('metadata', {})),
|
||||||
|
options = Options(**yaml_data.get('options', {})),
|
||||||
|
)
|
||||||
|
if 'title' not in harness.metadata:
|
||||||
|
harness.metadata['title'] = Path(file_out).stem
|
||||||
|
|
||||||
# add items
|
# add items
|
||||||
sections = ['connectors', 'cables', 'connections']
|
sections = ['connectors', 'cables', 'connections']
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from itertools import groupby
|
|||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||||
|
|
||||||
from wireviz.DataClasses import AdditionalComponent, Connector, Cable
|
from wireviz.DataClasses import AdditionalComponent, Connector, Cable
|
||||||
|
from wireviz.wv_colors import translate_color
|
||||||
from wireviz.wv_gv_html import html_line_breaks
|
from wireviz.wv_gv_html import html_line_breaks
|
||||||
from wireviz.wv_helper import clean_whitespace
|
from wireviz.wv_helper import clean_whitespace
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ def get_additional_component_table(harness: "Harness", component: Union[Connecto
|
|||||||
'qty': part.qty * component.get_qty_multiplier(part.qty_multiplier),
|
'qty': part.qty * component.get_qty_multiplier(part.qty_multiplier),
|
||||||
'unit': part.unit,
|
'unit': part.unit,
|
||||||
}
|
}
|
||||||
if harness.mini_bom_mode:
|
if harness.options.mini_bom_mode:
|
||||||
id = get_bom_index(harness.bom(), bom_entry_key({**asdict(part), 'description': part.description}))
|
id = get_bom_index(harness.bom(), bom_entry_key({**asdict(part), 'description': part.description}))
|
||||||
rows.append(component_table_entry(f'#{id} ({part.type.rstrip()})', **common_args))
|
rows.append(component_table_entry(f'#{id} ({part.type.rstrip()})', **common_args))
|
||||||
else:
|
else:
|
||||||
@ -69,7 +70,7 @@ def generate_bom(harness: "Harness") -> List[BOMEntry]:
|
|||||||
+ (f', {connector.type}' if connector.type else '')
|
+ (f', {connector.type}' if connector.type else '')
|
||||||
+ (f', {connector.subtype}' if connector.subtype else '')
|
+ (f', {connector.subtype}' if connector.subtype else '')
|
||||||
+ (f', {connector.pincount} pins' if connector.show_pincount else '')
|
+ (f', {connector.pincount} pins' if connector.show_pincount else '')
|
||||||
+ (f', {connector.color}' if connector.color else ''))
|
+ (f', {translate_color(connector.color, harness.options.color_mode)}' if connector.color else ''))
|
||||||
bom_entries.append({
|
bom_entries.append({
|
||||||
'description': description, 'designators': connector.name if connector.show_name else None,
|
'description': description, 'designators': connector.name if connector.show_name else None,
|
||||||
**optional_fields(connector),
|
**optional_fields(connector),
|
||||||
@ -88,7 +89,8 @@ def generate_bom(harness: "Harness") -> List[BOMEntry]:
|
|||||||
+ (f', {cable.type}' if cable.type else '')
|
+ (f', {cable.type}' if cable.type else '')
|
||||||
+ (f', {cable.wirecount}')
|
+ (f', {cable.wirecount}')
|
||||||
+ (f' x {cable.gauge} {cable.gauge_unit}' if cable.gauge else ' wires')
|
+ (f' x {cable.gauge} {cable.gauge_unit}' if cable.gauge else ' wires')
|
||||||
+ (' shielded' if cable.shield else ''))
|
+ ( ' shielded' if cable.shield else '')
|
||||||
|
+ (f', {translate_color(cable.color, harness.options.color_mode)}' if cable.color else ''))
|
||||||
bom_entries.append({
|
bom_entries.append({
|
||||||
'description': description, 'qty': cable.length, 'unit': cable.length_unit, 'designators': cable.name if cable.show_name else None,
|
'description': description, 'qty': cable.length, 'unit': cable.length_unit, 'designators': cable.name if cable.show_name else None,
|
||||||
**optional_fields(cable),
|
**optional_fields(cable),
|
||||||
@ -99,7 +101,7 @@ def generate_bom(harness: "Harness") -> List[BOMEntry]:
|
|||||||
description = ('Wire'
|
description = ('Wire'
|
||||||
+ (f', {cable.type}' if cable.type else '')
|
+ (f', {cable.type}' if cable.type else '')
|
||||||
+ (f', {cable.gauge} {cable.gauge_unit}' if cable.gauge else '')
|
+ (f', {cable.gauge} {cable.gauge_unit}' if cable.gauge else '')
|
||||||
+ (f', {color}' if color else ''))
|
+ (f', {translate_color(color, harness.options.color_mode)}' if color else ''))
|
||||||
bom_entries.append({
|
bom_entries.append({
|
||||||
'description': description, 'qty': cable.length, 'unit': cable.length_unit, 'designators': cable.name if cable.show_name else None,
|
'description': description, 'qty': cable.length, 'unit': cable.length_unit, 'designators': cable.name if cable.show_name else None,
|
||||||
**{k: index_if_list(v, index) for k, v in optional_fields(cable).items()},
|
**{k: index_if_list(v, index) for k, v in optional_fields(cable).items()},
|
||||||
|
|||||||
@ -2,21 +2,28 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import List, Union
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from wireviz import __version__, APP_NAME, APP_URL
|
from wireviz import __version__, APP_NAME, APP_URL, wv_colors
|
||||||
|
from wireviz.DataClasses import Metadata, Options
|
||||||
from wireviz.wv_helper import flatten2d, open_file_read, open_file_write
|
from wireviz.wv_helper import flatten2d, open_file_read, open_file_write
|
||||||
|
|
||||||
def generate_html_output(filename: (str, Path), bom_list):
|
def generate_html_output(filename: Union[str, Path], bom_list: List[List[str]], metadata: Metadata, options: Options):
|
||||||
with open_file_write(f'{filename}.html') as file:
|
with open_file_write(f'{filename}.html') as file:
|
||||||
file.write('<!DOCTYPE html>\n')
|
file.write('<!DOCTYPE html>\n')
|
||||||
file.write('<html lang="en"><head>\n')
|
file.write('<html lang="en"><head>\n')
|
||||||
file.write(' <meta charset="UTF-8">\n')
|
file.write(' <meta charset="UTF-8">\n')
|
||||||
file.write(f' <meta name="generator" content="{APP_NAME} {__version__} - {APP_URL}">\n')
|
file.write(f' <meta name="generator" content="{APP_NAME} {__version__} - {APP_URL}">\n')
|
||||||
file.write(f' <title>{APP_NAME} Diagram and BOM</title>\n')
|
file.write(f' <title>{metadata["title"]}</title>\n')
|
||||||
file.write('</head><body style="font-family:Arial">\n')
|
file.write(f'</head><body style="font-family:{options.fontname};background-color:'
|
||||||
|
f'{wv_colors.translate_color(options.bgcolor, "HEX")}">\n')
|
||||||
|
|
||||||
file.write('<h1>Diagram</h1>')
|
file.write(f'<h1>{metadata["title"]}</h1>\n')
|
||||||
|
description = metadata.get('description')
|
||||||
|
if description:
|
||||||
|
file.write(f'<p>{description}</p>\n')
|
||||||
|
file.write('<h2>Diagram</h2>\n')
|
||||||
with open_file_read(f'{filename}.svg') as svg:
|
with open_file_read(f'{filename}.svg') as svg:
|
||||||
file.write(re.sub(
|
file.write(re.sub(
|
||||||
'^<[?]xml [^?>]*[?]>[^<]*<!DOCTYPE [^>]*>',
|
'^<[?]xml [^?>]*[?]>[^<]*<!DOCTYPE [^>]*>',
|
||||||
@ -25,20 +32,24 @@ def generate_html_output(filename: (str, Path), bom_list):
|
|||||||
for svgdata in svg:
|
for svgdata in svg:
|
||||||
file.write(svgdata)
|
file.write(svgdata)
|
||||||
|
|
||||||
file.write('<h1>Bill of Materials</h1>')
|
file.write('<h2>Bill of Materials</h2>\n')
|
||||||
listy = flatten2d(bom_list)
|
listy = flatten2d(bom_list)
|
||||||
file.write('<table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px">')
|
file.write('<table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px">\n')
|
||||||
file.write('<tr>')
|
file.write(' <tr>\n')
|
||||||
for item in listy[0]:
|
for item in listy[0]:
|
||||||
file.write(f'<th style="text-align:left; border:1px solid #000000; padding: 8px">{item}</th>')
|
file.write(f' <th style="text-align:left; border:1px solid #000000; padding: 8px">{item}</th>\n')
|
||||||
file.write('</tr>')
|
file.write(' </tr>\n')
|
||||||
for row in listy[1:]:
|
for row in listy[1:]:
|
||||||
file.write('<tr>')
|
file.write(' <tr>\n')
|
||||||
for i, item in enumerate(row):
|
for i, item in enumerate(row):
|
||||||
item_str = item.replace('\u00b2', '²')
|
item_str = item.replace('\u00b2', '²')
|
||||||
align = 'text-align:right; ' if listy[0][i] == 'Qty' else ''
|
align = '; text-align:right' if listy[0][i] == 'Qty' else ''
|
||||||
file.write(f'<td style="{align}border:1px solid #000000; padding: 4px">{item_str}</td>')
|
file.write(f' <td style="border:1px solid #000000; padding: 4px{align}">{item_str}</td>\n')
|
||||||
file.write('</tr>')
|
file.write(' </tr>\n')
|
||||||
file.write('</table>')
|
file.write('</table>\n')
|
||||||
|
|
||||||
file.write('</body></html>')
|
notes = metadata.get('notes')
|
||||||
|
if notes:
|
||||||
|
file.write(f'<h2>Notes</h2>\n<p>{notes}</p>\n')
|
||||||
|
|
||||||
|
file.write('</body></html>\n')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user