Completed
Push — master ( 4274a7...754032 )
by Kolen
26s
created

table2csv()   F

Complexity

Conditions 9

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
cc 9
c 7
b 0
f 1
dl 0
loc 47
rs 3.3333
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 csv
53
import io
54
import panflute
55
import yaml
56
57
import sys
58
py2 = sys.version_info[0] == 2
59
60
61
def ast2markdown(ast):
62
    """
63
    A shorthand to convert panflute AST to Markdown
64
    """
65
    return panflute.convert_text(
66
        ast,
67
        input_format='panflute',
68
        output_format='markdown'
69
    )
70
71
72
def table2csv(elem, *__):
73
    """
74
    find Table element and return a csv table in code-block with class "table"
75
    """
76
    if isinstance(elem, panflute.Table):
77
        # get options as a dictionary
78
        options = {}
79
        # options: caption: panflute ast to markdown
80
        if elem.caption:
81
            options['caption'] = ast2markdown(panflute.Para(*elem.caption))
82
        # options: alignment
83
        align_dict = {"AlignLeft": 'L',
84
                      "AlignCenter": 'C',
85
                      "AlignRight": 'R',
86
                      "AlignDefault": 'D'}
87
        parsed_alignment = [align_dict[i] for i in elem.alignment]
88
        options['alignment'] = "".join(parsed_alignment)
89
        # options: width
90
        options['width'] = elem.width
91
        # options: table-width from width
92
        options['table-width'] = sum(options['width'])
93
        # options: header: False if empty header row, else True
94
        options['header'] = bool(panflute.stringify(elem.header))
95
        # options: markdown
96
        options['markdown'] = True
97
98
        # option in YAML
99
        yaml_metadata = yaml.safe_dump(options)
100
101
        # table in panflute AST
102
        table_body = elem.content
103
        if options['header']:
104
            table_body.insert(0, elem.header)
105
        # table in list
106
        table_list = [[ast2markdown(cell.content)
107
                       for cell in row.content]
108
                      for row in table_body]
109
        # table in CSV
110
        io_universal = io.BytesIO if py2 else io.StringIO
111
        with io_universal() as file:
112
            writer = csv.writer(file)
113
            writer.writerows(table_list)
114
            csv_table = file.getvalue()
115
        code_block = "{delimiter}{yaml}{delimiter}{csv}".format(
116
            yaml=yaml_metadata, csv=csv_table, delimiter='---\n')
117
        return panflute.CodeBlock(code_block, classes=["table"])
118
    return None
119
120
121
def main(_=None):
122
    """
123
    Any native pandoc tables will be converted into the CSV table format used by pantable:
124
125
    - in code-block with class table
126
    - metadata in YAML
127
    - table in CSV
128
    """
129
    panflute.run_filter(table2csv)
130
131
if __name__ == '__main__':
132
    main()
133