Completed
Push — master ( 4f6e16...4dcb1d )
by Christophe
24s
created

add_icon()   A

Complexity

Conditions 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
dl 0
loc 18
rs 9.2
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
    from pkg_resources import get_distribution
47
    from appdirs import AppDirs
48
    dirs = AppDirs('pandoc_latex_tip', version = get_distribution('pandoc_latex_tip').version)
49
    doc.getIconFont = icon_font_to_png.IconFont(
50
        dirs.user_data_dir + '/font-awesome.css',
51
        dirs.user_data_dir + '/fontawesome-webfont.ttf'
52
    )
53
54
    # Prepare the definitions
55
    doc.defined = []
56
57
    # Get the meta data
58
    meta = doc.get_metadata('pandoc-latex-tip')
59
60
    if isinstance(meta, list):
61
62
        # Loop on all definitions
63
        for definition in meta:
64
65
            # Verify the definition
66
            if isinstance(definition, dict) and 'classes' in definition and isinstance(definition['classes'], list):
67
                add_definition(doc, definition)
68
69
def finalize(doc):
70
    if 'header-includes' not in doc.metadata:
71
        doc.metadata['header-includes'] = []
72
    doc.metadata['header-includes'].append(MetaInlines(RawInline('\\usepackage{graphicx,grffile}', 'tex')))
73
    doc.metadata['header-includes'].append(MetaInlines(RawInline('\\usepackage{marginnote}', 'tex')))
74
    doc.metadata['header-includes'].append(MetaInlines(RawInline('\\usepackage{etoolbox}', 'tex')))
75
76
def latex_code(prefix, images):
77
    latex = [
78
        '{',
79
        '\\makeatletter',
80
        '\\patchcmd{\\@mn@margintest}{\\@tempswafalse}{\\@tempswatrue}{}{}',
81
        '\\patchcmd{\\@mn@margintest}{\\@tempswafalse}{\\@tempswatrue}{}{}',
82
        '\\makeatother',
83
        prefix,
84
        '\\marginnote{'
85
    ] + images + [
86
        '}[0pt]',
87
        '\\vspace{0cm}',
88
        '}',
89
    ]
90
    return ''.join(latex)
91
92
def get_icons(doc, definition):
93
    icons = [{'name': 'exclamation-circle', 'color': 'black'}]
94
95
    # Test the icons definition
96
    if 'icons' in definition and isinstance(definition['icons'], list):
97
        icons = []
98
        for icon in definition['icons']:
99
            check_icon(doc, icons, icon)
100
101
    return icons
102
103
def check_icon(doc, icons, icon):
104
    if isinstance(icon, str) or isinstance(icon, unicode):
105
        # Simple icon
106
        color = 'black'
107
        name = icon
108
    elif isinstance(icon, dict) and 'color' in icon and 'name' in icon:
109
        # Complex icon with name and color
110
        color = str(icon['color'])
111
        name = str(icon['name'])
112
    else:
113
        # Bad formed icon
114
        debug('[WARNING] pandoc-latex-tip: Bad formed icon')
115
        return
116
117
    add_icon(doc, icons, color, name)
118
119
def add_icon(doc, icons, color, name):
120
    # Lower the color
121
    lowerColor = color.lower()
122
123
    # Convert the color to black if unexisting
124
    from PIL import ImageColor
125
    if lowerColor not in ImageColor.colormap:
126
        debug('[WARNING] pandoc-latex-tip: ' + lowerColor + ' is not a correct color name; using black')
127
        lowerColor = 'black'
128
129
    # Is the icon correct?
130
    try:
131
        if name in doc.getIconFont.css_icons:
132
            icons.append({'name': name, 'color': lowerColor})
133
        else:
134
            debug('[WARNING] pandoc-latex-tip: ' + name + ' is not a correct icon name')
135
    except FileNotFoundError:
136
        debug('[WARNING] pandoc-latex-tip: error in accessing to icons definition')
137
138
def get_prefix(definition):
139
    if 'position' in definition:
140
        if definition['position'] == 'right':
141
            return '\\normalmarginpar'
142
        elif definition['position'] == 'left':
143
            return '\\reversemarginpar'
144
        else:
145
            debug('[WARNING] pandoc-latex-tip: ' + position + ' is not a correct position; using left')
146
            return '\\reversemarginpar'
147
    return '\\reversemarginpar'
148
149
def get_size(definition):
150
   # Get the size
151
    size = '18'
152
    if 'size' in definition:
153
        try:
154
            intValue = int(definition['size'])
155
            if intValue > 0:
156
                size = str(intValue)
157
            else:
158
                debug('[WARNING] pandoc-latex-tip: size must be greater than 0; using ' + size)
159
        except ValueError:
160
            debug('[WARNING] pandoc-latex-tip: size must be a number; using ' + size)
161
    return size
162
163
def get_images(doc, icons, size):
164
    # Generate the LaTeX image code
165
    images = []
166
167
    for icon in icons:
168
169
        # Get the apps dirs
170
        from pkg_resources import get_distribution
171
        from appdirs import AppDirs
172
        dirs = AppDirs('pandoc_latex_tip', version = get_distribution('pandoc_latex_tip').version)
173
174
        # Get the image from the App cache folder
175
        image = dirs.user_cache_dir + '/' + icon['color'] + '/' + icon['name'] + '.png'
176
177
        # Create the image if not existing in the cache
178
        try:
179
            if not os.path.isfile(image):
180
181
                # Create the image in the cache
182
                doc.getIconFont.export_icon(
183
                    icon['name'],
184
                    size = 512,
185
                    color = icon['color'],
186
                    export_dir = dirs.user_cache_dir + '/' + icon['color']
187
                )
188
189
            # Add the LaTeX image
190
            images.append('\\includegraphics[width=' + size + 'pt]{' + image + '}')
191
        except FileNotFoundError:
192
            debug('[WARNING] pandoc-latex-tip: error in generating image')
193
194
    return images
195
196
def add_definition(doc, definition):
197
    # Get the classes
198
    classes = definition['classes']
199
200
    # Get the icons
201
    icons = get_icons(doc, definition)
202
203
    # Add a definition if correct
204
    if bool(classes) and bool(icons):
205
206
        # Get the images
207
        images = get_images(doc, icons, get_size(definition))
208
209
        # Get the prefix
210
        prefix = get_prefix(definition)
211
212
        doc.defined.append({'classes' : set(classes), 'latex': latex_code(prefix, images)})
213
214
def main(doc = None):
215
    run_filter(tip, prepare = prepare, finalize = finalize, doc = doc)
216
217
if __name__ == '__main__':
218
    main()
219
220