Completed
Push — master ( 526ed2...286faa )
by Christophe
22s
created

add_latex()   A

Complexity

Conditions 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
#!/usr/bin/env python
2
3
"""
4
Pandoc filter for adding tip in LaTeX
5
"""
6
7
from panflute import *
8
import os
9
10
try:
11
    FileNotFoundError
12
except NameError:
13
    #py2
14
    FileNotFoundError = IOError
15
16
def add_latex(elem, latex):
17
    # Is it a Span or a Code?
18
    if isinstance(elem, Span) or isinstance(elem, Code):
19
        return [RawInline(latex, 'tex'), elem]
20
21
    # It is a Div or a CodeBlock
22
    else:
23
        return [RawBlock(latex, 'tex'), elem]
24
25
def tip(elem, doc):
26
    # Is it in the right format and is it a Span, Div?
27
    if doc.format == 'latex' and elem.tag in ['Span', 'Div', 'Code', 'CodeBlock']:
28
29
        # Is there a latex-tip-icon attribute?
30
        if 'latex-tip-icon' in elem.attributes:
31
            return add_latex(elem, latex_code(elem.attributes))
32
        else:
33
            # Get the classes
34
            classes = set(elem.classes)
35
36
            # Loop on all fontsize definition
37
            for definition in doc.defined:
38
39
                # Are the classes correct?
40
                if classes >= definition['classes']:
41
                    return add_latex(elem, definition['latex'])
42
43
def prepare(doc):
44
    # Add getIconFont library to doc
45
    import icon_font_to_png
46
    dir = os.path.dirname(os.path.realpath(__file__))
47
    doc.getIconFont = icon_font_to_png.IconFont(
48
        dir + '/pandoc_latex_tip-data/font-awesome.css',
49
        dir + '/pandoc_latex_tip-data/fontawesome-webfont.ttf'
50
    )
51
52
    # Prepare the definitions
53
    doc.defined = []
54
55
    # Get the meta data
56
    meta = doc.get_metadata('pandoc-latex-tip')
57
58
    if isinstance(meta, list):
59
60
        # Loop on all definitions
61
        for definition in meta:
62
63
            # Verify the definition
64
            if isinstance(definition, dict) and 'classes' in definition and isinstance(definition['classes'], list):
65
                add_definition(doc, definition)
66
67
def finalize(doc):
68
    if 'header-includes' not in doc.metadata:
69
        doc.metadata['header-includes'] = []
70
    doc.metadata['header-includes'].append(MetaInlines(RawInline('\\usepackage{graphicx,grffile}', 'tex')))
71
    doc.metadata['header-includes'].append(MetaInlines(RawInline('\\usepackage{marginnote}', 'tex')))
72
    doc.metadata['header-includes'].append(MetaInlines(RawInline('\\usepackage{etoolbox}', 'tex')))
73
74
def latex_code(prefix, images):
75
    latex = [
76
        '{',
77
        '\\makeatletter',
78
        '\\patchcmd{\\@mn@margintest}{\\@tempswafalse}{\\@tempswatrue}{}{}',
79
        '\\patchcmd{\\@mn@margintest}{\\@tempswafalse}{\\@tempswatrue}{}{}',
80
        '\\makeatother',
81
        prefix,
82
        '\\marginnote{'
83
    ] + images + [
84
        '}[0pt]',
85
        '\\vspace{0cm}',
86
        '}',
87
    ]
88
    return ''.join(latex)
89
90
def get_icons(doc, definition):
91
    icons = [{'name': 'exclamation-circle', 'color': 'black'}]
92
93
    # Test the icons definition
94
    if 'icons' in definition and isinstance(definition['icons'], list):
95
        icons = []
96
        for icon in definition['icons']:
97
            if isinstance(icon, str) or isinstance(icon, unicode):
98
                # Simple icon
99
                color = 'black'
100
                name = icon
101
            elif isinstance(icon, dict) and 'color' in icon and 'name' in icon:
102
                # Complex icon with name and color
103
                color = str(icon['color'])
104
                name = str(icon['name'])
105
            else:
106
                # Bad formed icon
107
                debug('[WARNING] pandoc-latex-tip: Bad formed icon')
108
                break
109
110
            # Lower the color
111
            lowerColor = color.lower()
112
113
            # Convert the color to black if unexisting
114
            from PIL import ImageColor
115
            if lowerColor not in ImageColor.colormap:
116
                debug('[WARNING] pandoc-latex-tip: ' + lowerColor + ' is not a correct color name; using black')
117
                lowerColor = 'black'
118
119
            # Is the icon correct?
120
            try:
121
                if name in doc.getIconFont.css_icons:
122
                    icons.append({'name': name, 'color': lowerColor})
123
                else:
124
                    debug('[WARNING] pandoc-latex-tip: ' + name + ' is not a correct icon name')
125
            except FileNotFoundError:
126
                debug('[WARNING] pandoc-latex-tip: error in accessing to icons definition')
127
128
    return icons
129
130
def get_prefix(definition):
131
    if 'position' in definition:
132
        if definition['position'] == 'right':
133
            return '\\normalmarginpar'
134
        elif definition['position'] == 'left':
135
            return '\\reversemarginpar'
136
        else:
137
            debug('[WARNING] pandoc-latex-tip: ' + position + ' is not a correct position; using left')
138
            return '\\reversemarginpar'
139
    return '\\reversemarginpar'
140
141
def get_size(definition):
142
   # Get the size
143
    size = '18'
144
    if 'size' in definition:
145
        try:
146
            intValue = int(definition['size'])
147
            if intValue > 0:
148
                size = str(intValue)
149
            else:
150
                debug('[WARNING] pandoc-latex-tip: size must be greater than 0; using ' + size)
151
        except ValueError:
152
            debug('[WARNING] pandoc-latex-tip: size must be a number; using ' + size)
153
    return size
154
155
def get_images(icons, size):
156
    # Generate the LaTeX image code
157
    images = []
158
159
    for icon in icons:
160
161
        # Get the apps dirs
162
        from pkg_resources import get_distribution
163
        from appdirs import AppDirs
164
        dirs = AppDirs('pandoc_latex_tip', version = get_distribution('pandoc_latex_tip').version)
165
166
        # Get the image from the App cache folder
167
        image = dirs.user_cache_dir + '/' + icon['color'] + '/' + icon['name'] + '.png'
168
169
        # Create the image if not existing in the cache
170
        try:
171
            if not os.path.isfile(image):
172
173
                # Create the image in the cache
174
                doc.getIconFont.export_icon(
175
                    icon['name'],
176
                    size = 512,
177
                    color = icon['color'],
178
                    export_dir = dirs.user_cache_dir + '/' + icon['color']
179
                )
180
181
            # Add the LaTeX image
182
            images.append('\\includegraphics[width=' + size + 'pt]{' + image + '}')
183
        except FileNotFoundError:
184
            debug('[WARNING] pandoc-latex-tip: error in generating image')
185
186
    return images
187
188
def add_definition(doc, definition):
189
    # Get the classes
190
    classes = definition['classes']
191
192
    # Get the icons
193
    icons = get_icons(doc, definition)
194
195
    # Add a definition if correct
196
    if bool(classes) and bool(icons):
197
198
        # Get the images
199
        images = get_images(icons, get_size(definition))
200
201
        # Get the prefix
202
        prefix = get_prefix(definition)
203
204
        doc.defined.append({'classes' : set(classes), 'latex': latex_code(prefix, images)})
205
206
def main(doc = None):
207
    run_filter(tip, prepare = prepare, finalize = finalize, doc = doc)
208
209
if __name__ == '__main__':
210
    main()
211
212