table2csv()   D
last analyzed

Complexity

Conditions 8

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 1
Metric Value
cc 8
c 8
b 0
f 1
dl 0
loc 46
rs 4.1666
1
r"""
2
Panflute filter to convert any native pandoc tables into the CSV table format used by pantable:
3
4
- in code-block with class table
5
- metadata in YAML
6
- table in CSV
7
8
e.g.
9
10
~~~markdown
11
+--------+---------------------+--------------------------+
12
| First  | defaulted to be     | can be disabled          |
13
| row    | header row          |                          |
14
+========+=====================+==========================+
15
| 1      | cell can contain    | It can be aribrary block |
16
|        | **markdown**        | element:                 |
17
|        |                     |                          |
18
|        |                     | -   following standard   |
19
|        |                     |     markdown syntax      |
20
|        |                     | -   like this            |
21
+--------+---------------------+--------------------------+
22
| 2      | Any markdown        | $$E = mc^2$$             |
23
|        | syntax, e.g.        |                          |
24
+--------+---------------------+--------------------------+
25
26
: *Awesome* **Markdown** Table
27
~~~
28
29
becomes
30
31
~~~markdown
32
``` {.table}
33
---
34
alignment: DDD
35
caption: '*Awesome* **Markdown** Table'
36
header: true
37
markdown: true
38
table-width: 0.8055555555555556
39
width: [0.125, 0.3055555555555556, 0.375]
40
---
41
First row,defaulted to be header row,can be disabled
42
1,cell can contain **markdown**,"It can be aribrary block element:
43
44
-   following standard markdown syntax
45
-   like this
46
"
47
2,"Any markdown syntax, e.g.",$$E = mc^2$$
48
```
49
~~~
50
"""
51
52
import io
53
import panflute
54
import yaml
55
56
import sys
57
py2 = sys.version_info[0] == 2
58
59
if py2:
60
    from backports import csv
61
else:
62
    import csv
63
64
65
def ast2markdown(ast):
66
    """
67
    A shorthand to convert panflute AST to Markdown
68
    """
69
    return panflute.convert_text(
70
        ast,
71
        input_format='panflute',
72
        output_format='markdown'
73
    )
74
75
76
def table2csv(elem, doc):
77
    """
78
    find Table element and return a csv table in code-block with class "table"
79
    """
80
    if isinstance(elem, panflute.Table):
81
        # get options as a dictionary
82
        options = {}
83
        # options: caption: panflute ast to markdown
84
        if elem.caption:
85
            options['caption'] = ast2markdown(panflute.Para(*elem.caption))
86
        # options: alignment
87
        align_dict = {"AlignLeft": 'L',
88
                      "AlignCenter": 'C',
89
                      "AlignRight": 'R',
90
                      "AlignDefault": 'D'}
91
        parsed_alignment = [align_dict[i] for i in elem.alignment]
92
        options['alignment'] = "".join(parsed_alignment)
93
        # options: width
94
        options['width'] = elem.width
95
        # options: table-width from width
96
        options['table-width'] = sum(options['width'])
97
        # options: header: False if empty header row, else True
98
        options['header'] = bool(panflute.stringify(elem.header))
99
        # options: markdown
100
        options['markdown'] = True
101
102
        # option in YAML
103
        yaml_metadata = yaml.safe_dump(options)
104
105
        # table in panflute AST
106
        table_body = elem.content
107
        if options['header']:
108
            table_body.insert(0, elem.header)
109
        # table in list
110
        table_list = [[ast2markdown(cell.content)
111
                       for cell in row.content]
112
                      for row in table_body]
113
        # table in CSV
114
        with io.StringIO() as file:
115
            writer = csv.writer(file)
116
            writer.writerows(table_list)
117
            csv_table = file.getvalue()
118
        code_block = "{delimiter}{yaml}{delimiter}{csv}".format(
119
            yaml=yaml_metadata, csv=csv_table, delimiter='---\n')
120
        return panflute.CodeBlock(code_block, classes=["table"])
121
    return None
122
123
124
def main(doc=None):
125
    """
126
    Any native pandoc tables will be converted into the CSV table format used by pantable:
127
128
    - in code-block with class table
129
    - metadata in YAML
130
    - table in CSV
131
    """
132
    return panflute.run_filter(
133
        table2csv,
134
        doc=doc
135
    )
136
137
if __name__ == '__main__':
138
    main()
139