Show More
@@ -1,115 +1,114 | |||
|
1 | 1 | """Latex filters. |
|
2 | 2 | |
|
3 | 3 | Module of useful filters for processing Latex within Jinja latex templates. |
|
4 | 4 | """ |
|
5 | 5 | #----------------------------------------------------------------------------- |
|
6 | 6 | # Copyright (c) 2013, the IPython Development Team. |
|
7 | 7 | # |
|
8 | 8 | # Distributed under the terms of the Modified BSD License. |
|
9 | 9 | # |
|
10 | 10 | # The full license is in the file COPYING.txt, distributed with this software. |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | |
|
13 | 13 | #----------------------------------------------------------------------------- |
|
14 | 14 | # Imports |
|
15 | 15 | #----------------------------------------------------------------------------- |
|
16 | 16 | import re |
|
17 | 17 | |
|
18 | 18 | #----------------------------------------------------------------------------- |
|
19 | 19 | # Globals and constants |
|
20 | 20 | #----------------------------------------------------------------------------- |
|
21 | 21 | |
|
22 | #Latex substitutions for escaping latex. | |
|
23 | LATEX_SUBS = ( | |
|
24 | (re.compile('\033\[[0-9;]+m'),''), # handle console escapes | |
|
25 | (re.compile(r'\\'), r'{\\textbackslash}'), | |
|
26 | (re.compile(r'([{}_#%&$])'), r'\\\1'), | |
|
27 | (re.compile(r'~'), r'\~{}'), | |
|
28 | (re.compile(r'\^'), r'\^{}'), | |
|
29 | (re.compile(r'"'), r"''"), | |
|
30 | (re.compile(r'\.\.\.+'), r'\\ldots'), | |
|
31 | ) | |
|
22 | # Latex substitutions for escaping latex. | |
|
23 | # see: http://stackoverflow.com/questions/16259923/how-can-i-escape-latex-special-characters-inside-django-templates | |
|
24 | LATEX_SUBS = { | |
|
25 | '&': r'\&', | |
|
26 | '%': r'\%', | |
|
27 | '$': r'\$', | |
|
28 | '#': r'\#', | |
|
29 | '_': r'\letterunderscore{}', | |
|
30 | '{': r'\letteropenbrace{}', | |
|
31 | '}': r'\letterclosebrace{}', | |
|
32 | '~': r'\lettertilde{}', | |
|
33 | '^': r'\letterhat{}', | |
|
34 | '\\': r'\letterbackslash{}'} | |
|
35 | ||
|
32 | 36 | |
|
33 | 37 | #----------------------------------------------------------------------------- |
|
34 | 38 | # Functions |
|
35 | 39 | #----------------------------------------------------------------------------- |
|
36 | 40 | |
|
37 | __all__ = [ | |
|
38 | 'escape_latex', | |
|
39 | 'strip_math_space' | |
|
40 | ] | |
|
41 | ||
|
41 | __all__ = ['escape_latex', | |
|
42 | 'strip_math_space'] | |
|
42 | 43 | |
|
43 | 44 | def escape_latex(text): |
|
44 | 45 | """ |
|
45 | 46 | Escape characters that may conflict with latex. |
|
46 | ||
|
47 | ||
|
47 | 48 | Parameters |
|
48 | 49 | ---------- |
|
49 | 50 | text : str |
|
50 | 51 | Text containing characters that may conflict with Latex |
|
51 | 52 | """ |
|
52 | return_text = text | |
|
53 | for pattern, replacement in LATEX_SUBS: | |
|
54 | return_text = pattern.sub(replacement, return_text) | |
|
55 | return return_text | |
|
53 | ||
|
54 | return ''.join([LATEX_SUBS.get(c, c) for c in text]) | |
|
56 | 55 | |
|
57 | 56 | |
|
58 | 57 | def strip_math_space(text): |
|
59 | 58 | """ |
|
60 | 59 | Remove the space between latex math commands and enclosing $ symbols. |
|
61 | 60 | This filter is important because latex isn't as flexible as the notebook |
|
62 | 61 | front end when it comes to flagging math using ampersand symbols. |
|
63 | 62 | |
|
64 | 63 | Parameters |
|
65 | 64 | ---------- |
|
66 | 65 | text : str |
|
67 | 66 | Text to filter. |
|
68 | 67 | """ |
|
69 | 68 | |
|
70 | 69 | # First, scan through the markdown looking for $. If |
|
71 | 70 | # a $ symbol is found, without a preceding \, assume |
|
72 | 71 | # it is the start of a math block. UNLESS that $ is |
|
73 | 72 | # not followed by another within two math_lines. |
|
74 | 73 | math_regions = [] |
|
75 | 74 | math_lines = 0 |
|
76 | 75 | within_math = False |
|
77 | 76 | math_start_index = 0 |
|
78 | 77 | ptext = '' |
|
79 | 78 | last_character = "" |
|
80 | 79 | skip = False |
|
81 | 80 | for index, char in enumerate(text): |
|
82 | 81 | |
|
83 | 82 | #Make sure the character isn't preceeded by a backslash |
|
84 | 83 | if (char == "$" and last_character != "\\"): |
|
85 | 84 | |
|
86 | 85 | # Close the math region if this is an ending $ |
|
87 | 86 | if within_math: |
|
88 | 87 | within_math = False |
|
89 | 88 | skip = True |
|
90 | 89 | ptext = ptext+'$'+text[math_start_index+1:index].strip()+'$' |
|
91 | 90 | math_regions.append([math_start_index, index+1]) |
|
92 | 91 | else: |
|
93 | 92 | |
|
94 | 93 | # Start a new math region |
|
95 | 94 | within_math = True |
|
96 | 95 | math_start_index = index |
|
97 | 96 | math_lines = 0 |
|
98 | 97 | |
|
99 | 98 | # If we are in a math region, count the number of lines parsed. |
|
100 | 99 | # Cancel the math region if we find two line breaks! |
|
101 | 100 | elif char == "\n": |
|
102 | 101 | if within_math: |
|
103 | 102 | math_lines += 1 |
|
104 | 103 | if math_lines > 1: |
|
105 | 104 | within_math = False |
|
106 | 105 | ptext = ptext+text[math_start_index:index] |
|
107 | 106 | |
|
108 | 107 | # Remember the last character so we can easily watch |
|
109 | 108 | # for backslashes |
|
110 | 109 | last_character = char |
|
111 | 110 | if not within_math and not skip: |
|
112 | 111 | ptext = ptext+char |
|
113 | 112 | if skip: |
|
114 | 113 | skip = False |
|
115 | 114 | return ptext |
@@ -1,65 +1,65 | |||
|
1 | 1 | """ |
|
2 | 2 | Module with tests for Latex |
|
3 | 3 | """ |
|
4 | 4 | |
|
5 | 5 | #----------------------------------------------------------------------------- |
|
6 | 6 | # Copyright (c) 2013, the IPython Development Team. |
|
7 | 7 | # |
|
8 | 8 | # Distributed under the terms of the Modified BSD License. |
|
9 | 9 | # |
|
10 | 10 | # The full license is in the file COPYING.txt, distributed with this software. |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | |
|
13 | 13 | #----------------------------------------------------------------------------- |
|
14 | 14 | # Imports |
|
15 | 15 | #----------------------------------------------------------------------------- |
|
16 | 16 | |
|
17 | 17 | from ...tests.base import TestsBase |
|
18 | 18 | from ..latex import escape_latex, strip_math_space |
|
19 | 19 | |
|
20 | 20 | |
|
21 | 21 | #----------------------------------------------------------------------------- |
|
22 | 22 | # Class |
|
23 | 23 | #----------------------------------------------------------------------------- |
|
24 | 24 | |
|
25 | 25 | class TestLatex(TestsBase): |
|
26 | 26 | |
|
27 | 27 | |
|
28 | 28 | def test_escape_latex(self): |
|
29 | 29 | """escape_latex test""" |
|
30 | 30 | tests = [ |
|
31 |
(r'How are \you doing today?', r'How are \ |
|
|
32 |
(r'\escapechar=`\A\catcode`\|=0 |string|foo', r'\ |
|
|
33 |
(r'# $ % & ~ _ ^ \ { }',r'\# \$ \% \& \ |
|
|
31 | (r'How are \you doing today?', r'How are \letterbackslash{}you doing today?'), | |
|
32 | (r'\escapechar=`\A\catcode`\|=0 |string|foo', r'\letterbackslash{}escapechar=`\letterbackslash{}A\letterbackslash{}catcode`\letterbackslash{}|=0 |string|foo'), | |
|
33 | (r'# $ % & ~ _ ^ \ { }', r'\# \$ \% \& \lettertilde{} \letterunderscore{} \letterhat{} \letterbackslash{} \letteropenbrace{} \letterclosebrace{}'), | |
|
34 | 34 | ('','')] |
|
35 | 35 | |
|
36 | 36 | for test in tests: |
|
37 | 37 | yield self._try_escape_latex(test[0], test[1]) |
|
38 | 38 | |
|
39 | 39 | |
|
40 | 40 | def _try_escape_latex(self, test, result): |
|
41 | 41 | """Try to remove latex from string""" |
|
42 | 42 | self.assertEqual(escape_latex(test), result) |
|
43 | 43 | |
|
44 | 44 | |
|
45 | 45 | def test_strip_math_space(self): |
|
46 | 46 | """strip_math_space test""" |
|
47 | 47 | tests = [ |
|
48 | 48 | ('$e$','$e$'), |
|
49 | 49 | ('$ e $','$e$'), |
|
50 | 50 | ('xxx$e^i$yyy','xxx$e^i$yyy'), |
|
51 | 51 | ('xxx$ e^i $yyy','xxx$e^i$yyy'), |
|
52 | 52 | ('xxx$e^i $yyy','xxx$e^i$yyy'), |
|
53 | 53 | ('xxx$ e^i$yyy','xxx$e^i$yyy'), |
|
54 | 54 | ('\$ e $ e $','\$ e $e$'), |
|
55 | 55 | ('','')] |
|
56 | 56 | |
|
57 | 57 | for test in tests: |
|
58 | 58 | yield self._try_strip_math_space(test[0], test[1]) |
|
59 | 59 | |
|
60 | 60 | |
|
61 | 61 | def _try_strip_math_space(self, test, result): |
|
62 | 62 | """ |
|
63 | 63 | Try to remove spaces between dollar symbols and contents correctly |
|
64 | 64 | """ |
|
65 | 65 | self.assertEqual(strip_math_space(test), result) |
General Comments 0
You need to be logged in to leave comments.
Login now