Completed
Push — master ( 286faa...5c1b3c )
by Christophe
20s
created

get_icons()   A

Complexity

Conditions 4

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
dl 0
loc 10
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
        	add_icon(doc, icons, icon)
100
101
    return icons
102
103
def add_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
    # Lower the color
118
    lowerColor = color.lower()
119
120
    # Convert the color to black if unexisting
121
    from PIL import ImageColor
122
    if lowerColor not in ImageColor.colormap:
123
        debug('[WARNING] pandoc-latex-tip: ' + lowerColor + ' is not a correct color name; using black')
124
        lowerColor = 'black'
125
126
    # Is the icon correct?
127
    try:
128
        if name in doc.getIconFont.css_icons:
129
            icons.append({'name': name, 'color': lowerColor})
130
        else:
131
            debug('[WARNING] pandoc-latex-tip: ' + name + ' is not a correct icon name')
132
    except FileNotFoundError:
133
        debug('[WARNING] pandoc-latex-tip: error in accessing to icons definition')
134
135
def get_prefix(definition):
136
    if 'position' in definition:
137
        if definition['position'] == 'right':
138
            return '\\normalmarginpar'
139
        elif definition['position'] == 'left':
140
            return '\\reversemarginpar'
141
        else:
142
            debug('[WARNING] pandoc-latex-tip: ' + position + ' is not a correct position; using left')
143
            return '\\reversemarginpar'
144
    return '\\reversemarginpar'
145
146
def get_size(definition):
147
   # Get the size
148
    size = '18'
149
    if 'size' in definition:
150
        try:
151
            intValue = int(definition['size'])
152
            if intValue > 0:
153
                size = str(intValue)
154
            else:
155
                debug('[WARNING] pandoc-latex-tip: size must be greater than 0; using ' + size)
156
        except ValueError:
157
            debug('[WARNING] pandoc-latex-tip: size must be a number; using ' + size)
158
    return size
159
160
def get_images(icons, size):
161
    # Generate the LaTeX image code
162
    images = []
163
164
    for icon in icons:
165
166
        # Get the apps dirs
167
        from pkg_resources import get_distribution
168
        from appdirs import AppDirs
169
        dirs = AppDirs('pandoc_latex_tip', version = get_distribution('pandoc_latex_tip').version)
170
171
        # Get the image from the App cache folder
172
        image = dirs.user_cache_dir + '/' + icon['color'] + '/' + icon['name'] + '.png'
173
174
        # Create the image if not existing in the cache
175
        try:
176
            if not os.path.isfile(image):
177
178
                # Create the image in the cache
179
                doc.getIconFont.export_icon(
180
                    icon['name'],
181
                    size = 512,
182
                    color = icon['color'],
183
                    export_dir = dirs.user_cache_dir + '/' + icon['color']
184
                )
185
186
            # Add the LaTeX image
187
            images.append('\\includegraphics[width=' + size + 'pt]{' + image + '}')
188
        except FileNotFoundError:
189
            debug('[WARNING] pandoc-latex-tip: error in generating image')
190
191
    return images
192
193
def add_definition(doc, definition):
194
    # Get the classes
195
    classes = definition['classes']
196
197
    # Get the icons
198
    icons = get_icons(doc, definition)
199
200
    # Add a definition if correct
201
    if bool(classes) and bool(icons):
202
203
        # Get the images
204
        images = get_images(icons, get_size(definition))
205
206
        # Get the prefix
207
        prefix = get_prefix(definition)
208
209
        doc.defined.append({'classes' : set(classes), 'latex': latex_code(prefix, images)})
210
211
def main(doc = None):
212
    run_filter(tip, prepare = prepare, finalize = finalize, doc = doc)
213
214
if __name__ == '__main__':
215
    main()
216
217