Completed
Push — master ( 546b1e...359945 )
by Kolen
01:09
created

ast2markdown()   A

Complexity

Conditions 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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