pydocmaker 2.2.7__tar.gz → 2.2.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydocmaker-2.2.7/src/pydocmaker.egg-info → pydocmaker-2.2.8}/PKG-INFO +1 -1
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/__init__.py +1 -1
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/baseformatter.py +43 -2
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/ex_docx.py +3 -1
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/ex_html.py +32 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/ex_ipynb.py +4 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/ex_markdown.py +32 -4
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/ex_redmine.py +35 -33
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/ex_tex.py +57 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/core.py +56 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8/src/pydocmaker.egg-info}/PKG-INFO +1 -1
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/tests/test_ex_html.py +14 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/LICENSE +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/README.md +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/setup.cfg +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/setup.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/__init__.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/mdx_latex.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/pandoc_api.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/backend/pdf_maker.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/templating.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker/util.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker.egg-info/SOURCES.txt +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker.egg-info/dependency_links.txt +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker.egg-info/requires.txt +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/src/pydocmaker.egg-info/top_level.txt +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/tests/test_backend_pandoc.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/tests/test_convert_all.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/tests/test_core.py +0 -0
- {pydocmaker-2.2.7 → pydocmaker-2.2.8}/tests/test_util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pydocmaker
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.8
|
|
4
4
|
Summary: a minimal document maker to make docx, markdown, html, textile, redmine, and tex documents from python. Written in pure python.
|
|
5
5
|
Home-page: https://github.com/TobiasGlaubach/pydocmaker
|
|
6
6
|
Author: Tobias Glaubach
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = '2.2.
|
|
1
|
+
__version__ = '2.2.8'
|
|
2
2
|
|
|
3
3
|
from pydocmaker.core import DocBuilder, construct, constr, buildingblocks, print_to_pdf, get_latex_compiler, set_latex_compiler, make_pdf_from_tex, show_pdf
|
|
4
4
|
from pydocmaker.util import upload_report_to_redmine, bcolors, txtcolor, colors_dc
|
|
@@ -31,7 +31,7 @@ class BaseFormatter(abc.ABC):
|
|
|
31
31
|
default_linebreak = '\n\n'
|
|
32
32
|
|
|
33
33
|
def digest_iterator(self, **kwargs):
|
|
34
|
-
content = kwargs.get('
|
|
34
|
+
content = kwargs.get('children', kwargs.get('content'))
|
|
35
35
|
return f''.join([self.digest(c) for c in content])
|
|
36
36
|
|
|
37
37
|
def digest_str(self, el):
|
|
@@ -46,6 +46,10 @@ class BaseFormatter(abc.ABC):
|
|
|
46
46
|
def digest_meta(self, **kwargs):
|
|
47
47
|
return '' # meta element will not influence the rendering and is just ignored
|
|
48
48
|
|
|
49
|
+
@abc.abstractmethod
|
|
50
|
+
def digest_table(self, children=None, **kwargs) -> str:
|
|
51
|
+
pass
|
|
52
|
+
|
|
49
53
|
@abc.abstractmethod
|
|
50
54
|
def digest_markdown(self, children='', **kwargs) -> str:
|
|
51
55
|
pass
|
|
@@ -65,13 +69,14 @@ class BaseFormatter(abc.ABC):
|
|
|
65
69
|
def digest(self, children, **kwargs) -> str:
|
|
66
70
|
try:
|
|
67
71
|
|
|
68
|
-
|
|
69
72
|
if not children:
|
|
70
73
|
ret = ''
|
|
71
74
|
elif isinstance(children, str):
|
|
72
75
|
ret = self.digest_str(children)
|
|
73
76
|
elif isinstance(children, dict) and children.get('typ', None) == 'meta':
|
|
74
77
|
ret = self.digest_meta(children=children, **kwargs)
|
|
78
|
+
elif isinstance(children, dict) and children.get('typ', None) == 'table':
|
|
79
|
+
ret = self.digest_table(**children, **kwargs)
|
|
75
80
|
elif isinstance(children, dict) and children.get('typ', None) == 'iter':
|
|
76
81
|
ret = self.digest_iterator(children=children, **kwargs)
|
|
77
82
|
elif isinstance(children, list) and children:
|
|
@@ -103,9 +108,11 @@ class BaseFormatter(abc.ABC):
|
|
|
103
108
|
linebreak = tmp
|
|
104
109
|
|
|
105
110
|
ret += linebreak
|
|
111
|
+
|
|
106
112
|
return ret
|
|
107
113
|
|
|
108
114
|
except Exception as err:
|
|
115
|
+
raise
|
|
109
116
|
return self.handle_error(err, children)
|
|
110
117
|
|
|
111
118
|
|
|
@@ -131,3 +138,37 @@ class BaseFormatter(abc.ABC):
|
|
|
131
138
|
|
|
132
139
|
|
|
133
140
|
|
|
141
|
+
def _map_table2mat(self, children=None, **kwargs) -> str:
|
|
142
|
+
if children is None:
|
|
143
|
+
children = [[]]
|
|
144
|
+
|
|
145
|
+
assert isinstance(children, (list, tuple)), f'children must be of type list! but was {type(children)=} {children=}'
|
|
146
|
+
header = kwargs.get('header', None)
|
|
147
|
+
header = list(header) if header else []
|
|
148
|
+
|
|
149
|
+
assert isinstance(header, (list, tuple)), f'header must be of type list! but was {type(header)=} {header=}'
|
|
150
|
+
data = list(children)
|
|
151
|
+
wrong_rows = [row for row in children if not isinstance(row, (list, tuple))]
|
|
152
|
+
assert not wrong_rows, f'all rows must be of type list! but found {wrong_rows=}'
|
|
153
|
+
|
|
154
|
+
n_rows = kwargs.get('n_rows', None)
|
|
155
|
+
if n_rows is None:
|
|
156
|
+
n_rows = len(data)
|
|
157
|
+
n_cols = kwargs.get('n_cols', None)
|
|
158
|
+
if n_cols is None:
|
|
159
|
+
n_cols = max(len(header), max([len(row) for row in data]))
|
|
160
|
+
|
|
161
|
+
head = [self.digest(el) for el in header]
|
|
162
|
+
if len(head) < n_cols:
|
|
163
|
+
head += ['']*(n_cols-len(head))
|
|
164
|
+
|
|
165
|
+
mat = []
|
|
166
|
+
for i in range(n_rows):
|
|
167
|
+
mat.append(['']*n_cols)
|
|
168
|
+
|
|
169
|
+
for irow, row in enumerate(data):
|
|
170
|
+
for icol, el in enumerate(row):
|
|
171
|
+
mat[irow][icol] = self.digest(el)
|
|
172
|
+
|
|
173
|
+
return head, mat
|
|
174
|
+
|
|
@@ -98,7 +98,9 @@ class docx_renderer(BaseFormatter):
|
|
|
98
98
|
return [self.digest(val, *args, **kwargs) for val in children]
|
|
99
99
|
return []
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
def digest_table(self, children=None, **kwargs) -> str:
|
|
102
|
+
self.handle_error(NotImplementedError(f'exporter of type {type(self)} can not handle tables'))
|
|
103
|
+
|
|
102
104
|
def digest_image(self, children, *args, **kwargs):
|
|
103
105
|
|
|
104
106
|
image_width = Inches(max(1, kwargs.get('width', 0.8)*5))
|
|
@@ -225,3 +225,35 @@ class html_renderer(BaseFormatter):
|
|
|
225
225
|
children += [f'<div style="width: 100%; text-align: center;"><span style="min-width:100;display: inline-block;"><b>caption: </b>{caption}</span></div>']
|
|
226
226
|
|
|
227
227
|
return '\n\n'.join(children)
|
|
228
|
+
|
|
229
|
+
def digest_table(self, children=None, **kwargs) -> str:
|
|
230
|
+
borders = kwargs.pop('borders', None)
|
|
231
|
+
if borders is None:
|
|
232
|
+
borders = True
|
|
233
|
+
caption = kwargs.pop('caption', '')
|
|
234
|
+
if not caption:
|
|
235
|
+
caption = ''
|
|
236
|
+
|
|
237
|
+
head, mat = self._map_table2mat(children=children, **kwargs)
|
|
238
|
+
lines = []
|
|
239
|
+
st = ' style="border: 1px solid black;"' if borders else ''
|
|
240
|
+
|
|
241
|
+
lines.append('<table style="border-collapse: collapse; margin-left: auto; margin-right: auto;">')
|
|
242
|
+
lines.append(" <tr>")
|
|
243
|
+
lines += [f" <th{st}>{h}</th>" for h in head]
|
|
244
|
+
lines.append(" </tr>")
|
|
245
|
+
for row in mat:
|
|
246
|
+
lines.append(" <tr>")
|
|
247
|
+
lines += [f" <td{st}>{cell}</td>" for cell in row]
|
|
248
|
+
lines.append(" </tr>")
|
|
249
|
+
|
|
250
|
+
lines.append("</table>")
|
|
251
|
+
|
|
252
|
+
body = '\n'.join(lines)
|
|
253
|
+
txt = f'<div>{body}</div>'
|
|
254
|
+
|
|
255
|
+
if caption:
|
|
256
|
+
txt += f'\n<div style="text-align: center;"><span style="min-width:100;display: inline-block;"><b>Caption: </b>{caption}</span></div>'
|
|
257
|
+
|
|
258
|
+
return txt
|
|
259
|
+
|
|
@@ -191,6 +191,10 @@ class ipynb_renderer(BaseFormatter):
|
|
|
191
191
|
self.cells += [make_markdown(content)]
|
|
192
192
|
return ''
|
|
193
193
|
|
|
194
|
+
def digest_table(self, children=None, **kwargs) -> str:
|
|
195
|
+
self.handle_error(NotImplementedError(f'exporter of type {type(self)} can not handle tables'))
|
|
196
|
+
|
|
197
|
+
|
|
194
198
|
def digest_image(self,imageblob=None, children='', width=0.8, caption="", **kwargs):
|
|
195
199
|
|
|
196
200
|
if imageblob is None:
|
|
@@ -23,6 +23,29 @@ class DocumentMarkdownFormatter(BaseFormatter):
|
|
|
23
23
|
def digest_markdown(self, children='', **kwargs) -> list:
|
|
24
24
|
return children
|
|
25
25
|
|
|
26
|
+
def digest_table(self, children=None, **kwargs) -> str:
|
|
27
|
+
borders = kwargs.pop('borders', None)
|
|
28
|
+
if borders is None:
|
|
29
|
+
borders = True
|
|
30
|
+
caption = kwargs.pop('caption', '')
|
|
31
|
+
if not caption:
|
|
32
|
+
caption = ''
|
|
33
|
+
|
|
34
|
+
head, mat = self._map_table2mat(children=children, **kwargs)
|
|
35
|
+
striprow = lambda x: [str(xx).strip() for xx in x]
|
|
36
|
+
|
|
37
|
+
header = '| ' + ' | '.join(striprow(head)) + ' |'
|
|
38
|
+
separator = '|' + (' --- |' if borders else ' ---:|') * len(head)
|
|
39
|
+
rows = ['| ' + ' | '.join(striprow(row)) + ' |' for row in mat]
|
|
40
|
+
body = '\n'.join([header, separator] + rows)
|
|
41
|
+
|
|
42
|
+
if caption:
|
|
43
|
+
body += f'\n\n**Caption:** {caption}\n'
|
|
44
|
+
|
|
45
|
+
return body
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
26
49
|
def digest_image(self, **kwargs) -> list:
|
|
27
50
|
|
|
28
51
|
filename = kwargs.get('filename')
|
|
@@ -49,18 +72,23 @@ class DocumentMarkdownFormatter(BaseFormatter):
|
|
|
49
72
|
lines.append('')
|
|
50
73
|
|
|
51
74
|
# HACK: handle non PNG type properly!
|
|
75
|
+
if imageblob.startswith('data:image/png;base64,'):
|
|
76
|
+
i = imageblob
|
|
77
|
+
else:
|
|
78
|
+
i = 'data:image/png;base64,' + str(imageblob)
|
|
79
|
+
|
|
52
80
|
if self.embed_images:
|
|
53
|
-
lines.append(f'')
|
|
54
82
|
else:
|
|
55
|
-
i =
|
|
56
|
-
lines.append(f'#[{description}](
|
|
83
|
+
i = i[:35] + f'... (n={len(i)-35} more chars hidden))' if len(i) > 35 else i
|
|
84
|
+
lines.append(f'#[{description}]({i}')
|
|
57
85
|
lines.append('')
|
|
58
86
|
|
|
59
87
|
if caption:
|
|
60
88
|
lines.append(f'*caption:* {filename}')
|
|
61
89
|
lines.append('')
|
|
62
90
|
|
|
63
|
-
return lines
|
|
91
|
+
return '\n'.join(lines)
|
|
64
92
|
|
|
65
93
|
|
|
66
94
|
def digest_verbatim(self, children='', **kwargs) -> list:
|
|
@@ -5,7 +5,12 @@ try:
|
|
|
5
5
|
from pydocmaker.backend.baseformatter import BaseFormatter
|
|
6
6
|
except Exception as err:
|
|
7
7
|
from .baseformatter import BaseFormatter
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from pydocmaker.backend.pandoc_api import can_run_pandoc, pandoc_convert
|
|
11
|
+
except Exception as err:
|
|
12
|
+
from .pandoc_api import can_run_pandoc, pandoc_convert
|
|
13
|
+
|
|
9
14
|
|
|
10
15
|
def convert(doc:List[dict], with_attachments=True, aformat_redmine=False):
|
|
11
16
|
|
|
@@ -89,12 +94,16 @@ class DocumentRedmineFormatter(BaseFormatter):
|
|
|
89
94
|
|
|
90
95
|
@handle_color
|
|
91
96
|
def digest_markdown(self, children='', **kwargs) -> str:
|
|
92
|
-
|
|
97
|
+
if can_run_pandoc():
|
|
98
|
+
return pandoc_convert(children, 'markdown', 'textile')
|
|
99
|
+
else:
|
|
100
|
+
return children
|
|
93
101
|
|
|
94
102
|
@handle_color
|
|
95
103
|
def digest_text(self, children='', **kwargs) -> str:
|
|
96
104
|
return children
|
|
97
105
|
|
|
106
|
+
|
|
98
107
|
def digest_image(self, **kwargs) -> str:
|
|
99
108
|
filename, content = im2file(kwargs)
|
|
100
109
|
attachment = im2attachment(kwargs, filename, content)
|
|
@@ -110,8 +119,11 @@ class DocumentRedmineFormatter(BaseFormatter):
|
|
|
110
119
|
return s
|
|
111
120
|
|
|
112
121
|
def digest_latex(self, children='', **kwargs) -> str:
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
if can_run_pandoc():
|
|
123
|
+
return pandoc_convert(children, 'latex', 'textile')
|
|
124
|
+
else:
|
|
125
|
+
return self.digest_verbatim(children=children, **kwargs)
|
|
126
|
+
|
|
115
127
|
@handle_color
|
|
116
128
|
def digest_verbatim(self, children='', **kwargs) -> str:
|
|
117
129
|
if isinstance(children, str):
|
|
@@ -123,33 +135,23 @@ class DocumentRedmineFormatter(BaseFormatter):
|
|
|
123
135
|
return s
|
|
124
136
|
|
|
125
137
|
|
|
126
|
-
def
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
line = line.replace(g, ('*'*len(g)) + ' ')
|
|
139
|
-
|
|
140
|
-
return line
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def parse_md2textile(self, s) -> str:
|
|
145
|
-
f = self.parse_md2textile_line
|
|
146
|
-
lines = [f(line) for line in s.split('\n')]
|
|
147
|
-
s = '\n'.join(lines)
|
|
148
|
-
# code blocks
|
|
149
|
-
s = re.sub(r"(```)([\s\S]*?)(?=```)(```)", r'<pre>\2</pre>', s)
|
|
150
|
-
|
|
151
|
-
# links
|
|
152
|
-
s = re.sub(r"(\[)([\s\S]*?)(?=\])(\])(\()([\s\S]*?)(?=\))(\))", r'"\2":\5', s)
|
|
138
|
+
def digest_table(self, children=None, **kwargs) -> str:
|
|
139
|
+
borders = kwargs.pop('borders', None)
|
|
140
|
+
if borders is None:
|
|
141
|
+
borders = True
|
|
142
|
+
caption = kwargs.pop('caption', '')
|
|
143
|
+
if not caption:
|
|
144
|
+
caption = ''
|
|
145
|
+
|
|
146
|
+
head, mat = self._map_table2mat(children=children, **kwargs)
|
|
147
|
+
striprow = lambda x: [str(xx).strip() for xx in x]
|
|
148
|
+
|
|
149
|
+
header = '|_.' + ' |_.'.join(striprow(head)) + ' |'
|
|
153
150
|
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
rows = ['| ' + ' |'.join(striprow(row)) + ' |' for row in mat]
|
|
152
|
+
body = '\n'.join([header] + rows)
|
|
153
|
+
if caption:
|
|
154
|
+
body += f'\n\nCaption: {caption}\n'
|
|
155
|
+
return body
|
|
156
|
+
|
|
157
|
+
|
|
@@ -427,3 +427,60 @@ class LatexElementFormatter(BaseFormatter):
|
|
|
427
427
|
def digest_line(self, children:str, **kwargs):
|
|
428
428
|
return replace_bcolors(str(children))
|
|
429
429
|
|
|
430
|
+
|
|
431
|
+
def digest_table(self, children=None, **kwargs) -> str:
|
|
432
|
+
borders = kwargs.pop('borders', None)
|
|
433
|
+
if borders is None:
|
|
434
|
+
borders = True
|
|
435
|
+
|
|
436
|
+
caption = kwargs.pop('caption', '')
|
|
437
|
+
if not caption:
|
|
438
|
+
caption = ''
|
|
439
|
+
|
|
440
|
+
head, mat = self._map_table2mat(children=children, **kwargs)
|
|
441
|
+
if not head and not mat[0]:
|
|
442
|
+
return ''
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
striprow = lambda x: [str(xx).strip() for xx in x]
|
|
446
|
+
bold = lambda x: '\\textbf{' + str(x).strip() + '}'
|
|
447
|
+
|
|
448
|
+
n_cols = len(head) if head else len(mat[0])
|
|
449
|
+
|
|
450
|
+
lines = []
|
|
451
|
+
if borders:
|
|
452
|
+
lines.append(r'\hline')
|
|
453
|
+
|
|
454
|
+
if head:
|
|
455
|
+
lines.append(' & '.join([bold(hh) for hh in head]) + r' \\')
|
|
456
|
+
if borders:
|
|
457
|
+
lines.append(r'\hline')
|
|
458
|
+
for row in mat:
|
|
459
|
+
lines.append(' & '.join(striprow(row)) + r' \\')
|
|
460
|
+
if borders:
|
|
461
|
+
lines.append(r'\hline')
|
|
462
|
+
|
|
463
|
+
if not borders:
|
|
464
|
+
d = ' '.join(['c'] * n_cols)
|
|
465
|
+
else:
|
|
466
|
+
d = '|' + '|'.join(['c'] * n_cols) + '|'
|
|
467
|
+
|
|
468
|
+
if caption:
|
|
469
|
+
caption = '\\caption{%s}' % (escape(caption))
|
|
470
|
+
|
|
471
|
+
txt = '''\\begin{table}[h!]
|
|
472
|
+
\centering
|
|
473
|
+
\\begin{tabular}{ %s }
|
|
474
|
+
%s
|
|
475
|
+
\end{tabular}
|
|
476
|
+
%s
|
|
477
|
+
\end{table}''' % (d, '\n'.join(lines), caption)
|
|
478
|
+
else:
|
|
479
|
+
txt = '''\\begin{center}
|
|
480
|
+
\\begin{tabular}{ %s }
|
|
481
|
+
%s
|
|
482
|
+
\end{tabular}
|
|
483
|
+
\end{center}''' % (d, '\n'.join(lines))
|
|
484
|
+
|
|
485
|
+
return txt
|
|
486
|
+
|
|
@@ -144,6 +144,15 @@ class constr():
|
|
|
144
144
|
'end': end
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
@staticmethod
|
|
148
|
+
def line(children='', color='', end=None):
|
|
149
|
+
return {
|
|
150
|
+
'typ': 'line',
|
|
151
|
+
'children': children,
|
|
152
|
+
'color': color,
|
|
153
|
+
'end': '\n' if end is None else end
|
|
154
|
+
}
|
|
155
|
+
|
|
147
156
|
@staticmethod
|
|
148
157
|
def latex(children='', color='', end=None):
|
|
149
158
|
return {
|
|
@@ -172,6 +181,20 @@ class constr():
|
|
|
172
181
|
'end': end
|
|
173
182
|
}
|
|
174
183
|
|
|
184
|
+
@staticmethod
|
|
185
|
+
def table(children:list=None, color='', end=None, header=None, caption=None, n_cols=None, n_rows=None, borders=True):
|
|
186
|
+
return {
|
|
187
|
+
'typ': 'table',
|
|
188
|
+
'children': children,
|
|
189
|
+
'n_cols': n_cols,
|
|
190
|
+
'n_rows': n_rows,
|
|
191
|
+
'borders': borders,
|
|
192
|
+
'header': header,
|
|
193
|
+
'caption': caption,
|
|
194
|
+
'color': color,
|
|
195
|
+
'end': end,
|
|
196
|
+
}
|
|
197
|
+
|
|
175
198
|
@staticmethod
|
|
176
199
|
def image(imageblob='', caption='', children='', width=0.8, color='', end=None):
|
|
177
200
|
|
|
@@ -789,7 +812,29 @@ class DocBuilder(UserList):
|
|
|
789
812
|
self.add(construct('markdown', children=children, color=color, end=end, **kwargs), index=index, chapter=chapter)
|
|
790
813
|
return self
|
|
791
814
|
|
|
815
|
+
def add_table(self, children=None, index=None, chapter=None, color='', end=None, header=None, caption='', n_rows=None, n_cols=None, borders=True, **kwargs):
|
|
816
|
+
"""add a table element to this document
|
|
792
817
|
|
|
818
|
+
Args:
|
|
819
|
+
children (list of lists): the "children" for this element. Must be a matrix (list of lists) with formatable elements in it.
|
|
820
|
+
index (int, optional): The index where to insert the part. If None, appends to the end.
|
|
821
|
+
chapter (str | int, optional): The chapter name or index where to insert the part. If None, appends to the end.
|
|
822
|
+
color (str, optional): any color which can be rendered by html or latex. Empty string for default.
|
|
823
|
+
end (str, optional): If you want to insert a different line ending (than the default) for this element set this argument to any string. None for default.
|
|
824
|
+
header (list, optional): The header row for the table. If given it must be a list with formatable elements in it.
|
|
825
|
+
caption (str, optional): The caption to place at/under the table. Empty for no caption.
|
|
826
|
+
n_rows (int, optional): The number of rows to give this table. If not given it will be determined from the number of rows in children.
|
|
827
|
+
n_cols (int, optional): The number of columns to give this table. If not given it will be determined from the max number of columns in all rows in children.
|
|
828
|
+
borders (bool, optional): Whether or not the table should have lines between its cells.
|
|
829
|
+
"""
|
|
830
|
+
if header: kwargs['header'] = header
|
|
831
|
+
if n_rows: kwargs['n_rows'] = n_rows
|
|
832
|
+
if n_cols: kwargs['n_cols'] = n_cols
|
|
833
|
+
if borders: kwargs['borders'] = borders
|
|
834
|
+
if caption: kwargs['caption'] = caption
|
|
835
|
+
self.add(constr.table(children=children, color=color, end=end, **kwargs), index=index, chapter=chapter)
|
|
836
|
+
return self
|
|
837
|
+
|
|
793
838
|
def add_pre(self, children=None, index=None, chapter=None, color='', end=None, **kwargs):
|
|
794
839
|
"""add a verbaim (pre formatted) document part to this document
|
|
795
840
|
|
|
@@ -1495,6 +1540,17 @@ function metamorphose(protagonist,author){
|
|
|
1495
1540
|
}
|
|
1496
1541
|
""")
|
|
1497
1542
|
doc.add_tex("\\textit{This is some dummy LaTeX text.}")
|
|
1543
|
+
|
|
1544
|
+
doc.add_md("this is how to embed a table:")
|
|
1545
|
+
|
|
1546
|
+
header = ['Name', 'Age', 'City']
|
|
1547
|
+
table = [
|
|
1548
|
+
['John Doe', "30", 'New York'],
|
|
1549
|
+
['Jane Smith', "25", 'Los Angeles'],
|
|
1550
|
+
['Mike Johnson', "35", 'Chicago']
|
|
1551
|
+
]
|
|
1552
|
+
doc.add_table(table, header=header, borders=True, caption='This is my example table')
|
|
1553
|
+
|
|
1498
1554
|
doc.add('And this is how to embed an Image:')
|
|
1499
1555
|
doc.add_image(image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAAAUCAAAAAAVAxSkAAABrUlEQVQ4y+3TPUvDQBgH8OdDOGa+oUMgk2MpdHIIgpSUiqC0OKirgxYX8QVFRQRpBRF8KShqLbgIYkUEteCgFVuqUEVxEIkvJFhae3m8S2KbSkcFBw9yHP88+eXucgH8kQZ/jSm4VDaIy9RKCpKac9NKgU4uEJNwhHhK3qvPBVO8rxRWmFXPF+NSM1KVMbwriAMwhDgVcrxeMZm85GR0PhvGJAAmyozJsbsxgNEir4iEjIK0SYqGd8sOR3rJAGN2BCEkOxhxMhpd8Mk0CXtZacxi1hr20mI/rzgnxayoidevcGuHXTC/q6QuYSMt1jC+gBIiMg12v2vb5NlklChiWnhmFZpwvxDGzuUzV8kOg+N8UUvNBp64vy9q3UN7gDXhwWLY2nMC3zRDibfsY7wjEkY79CdMZhrxSqqzxf4ZRPXwzWJirMicDa5KwiPeARygHXKNMQHEy3rMopDR20XNZGbJzUtrwDC/KshlLDWyqdmhxZzCsdYmf2fWZPoxCEDyfIvdtNQH0PRkH6Q51g8rFO3Qzxh2LbItcDCOpmuOsV7ntNaERe3v/lP/zO8yn4N+yNPrekmPAAAAAElFTkSuQmCC")
|
|
1500
1556
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pydocmaker
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.8
|
|
4
4
|
Summary: a minimal document maker to make docx, markdown, html, textile, redmine, and tex documents from python. Written in pure python.
|
|
5
5
|
Home-page: https://github.com/TobiasGlaubach/pydocmaker
|
|
6
6
|
Author: Tobias Glaubach
|
|
@@ -32,6 +32,19 @@ class TestHtmlRenderer(unittest.TestCase):
|
|
|
32
32
|
result = self.formatter.digest({'typ': 'verbatim'})
|
|
33
33
|
self.assertIsInstance(result, str)
|
|
34
34
|
|
|
35
|
+
def test_digest_table(self):
|
|
36
|
+
result = self.formatter.digest([['element1', 'element2']])
|
|
37
|
+
self.assertIsInstance(result, str)
|
|
38
|
+
|
|
39
|
+
dc = {
|
|
40
|
+
'children': [['element1', 'element2']],
|
|
41
|
+
'header': ['h1', 'h2'],
|
|
42
|
+
'n_cols': 3,
|
|
43
|
+
'typ': 'table'
|
|
44
|
+
}
|
|
45
|
+
result = self.formatter.digest(dc)
|
|
46
|
+
self.assertIsInstance(result, str)
|
|
47
|
+
|
|
35
48
|
def test_digest_iterator(self):
|
|
36
49
|
result = self.formatter.digest(['element1', 'element2'])
|
|
37
50
|
self.assertIsInstance(result, str)
|
|
@@ -62,6 +75,7 @@ class TestHtmlRenderer(unittest.TestCase):
|
|
|
62
75
|
self.assertIsInstance(res, str)
|
|
63
76
|
self.assertTrue(res)
|
|
64
77
|
|
|
78
|
+
|
|
65
79
|
if __name__ == '__main__':
|
|
66
80
|
unittest.main()
|
|
67
81
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|