##// END OF EJS Templates
Adding citation support.
Brian E. Granger -
Show More
@@ -0,0 +1,70 b''
1 """Citation handling for LaTeX output."""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Code
13 #-----------------------------------------------------------------------------
14
15
16 __all__ = ['parse_citation']
17
18
19 def parse_citation(s):
20 """Parse citations in Markdown cells.
21
22 This looks for HTML tags having a data attribute names `data-cite`
23 and replaces it by the call to LaTeX cite command. The tranformation
24 looks like this:
25
26 `<cite data-cite="granger">(Granger, 2013)</cite>`
27
28 Becomes
29
30 `\\cite{granger}`
31
32 Any HTML tag can be used, which allows the citations to be formatted
33 in HTML in any manner.
34 """
35 try:
36 from lxml import html
37 except ImportError:
38 return s
39
40 tree = html.fragment_fromstring(s, create_parent='div')
41 _process_node_cite(tree)
42 s = html.tostring(tree)
43 s = s.lstrip('<div>')
44 s = s.rstrip('</div>')
45 return s
46
47
48 def _process_node_cite(node):
49 """Do the citation replacement as we walk the lxml tree."""
50
51 def _get(o, name):
52 value = getattr(o, name)
53 return '' if value is None else value
54
55 if 'data-cite' in node.attrib:
56 cite = '\cite{%(ref)s}' % {'ref': node.attrib['data-cite']}
57 prev = node.getprevious()
58 if prev is not None:
59 prev.tail = _get(prev, 'tail') + cite + _get(node, 'tail')
60 else:
61 parent = node.getparent()
62 if parent is not None:
63 parent.text = _get(parent, 'text') + cite + _get(node, 'tail')
64 try:
65 node.getparent().remove(node)
66 except AttributeError:
67 pass
68 else:
69 for child in node:
70 _process_node_cite(child)
@@ -0,0 +1,54 b''
1 #-----------------------------------------------------------------------------
2 # Copyright (c) 2013, the IPython Development Team.
3 #
4 # Distributed under the terms of the Modified BSD License.
5 #
6 # The full license is in the file COPYING.txt, distributed with this software.
7 #-----------------------------------------------------------------------------
8
9 #-----------------------------------------------------------------------------
10 # Imports
11 #-----------------------------------------------------------------------------
12
13 from ..citation import parse_citation
14
15 #-----------------------------------------------------------------------------
16 # Tests
17 #-----------------------------------------------------------------------------
18
19 test_md = """
20 # My Heading
21
22 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac magna non augue
23 porttitor scelerisque ac id diam <cite data-cite="granger">Granger</cite>. Mauris elit
24 velit, lobortis sed interdum at, vestibulum vitae libero <strong data-cite="fperez">Perez</strong>.
25 Lorem ipsum dolor sit amet, consectetur adipiscing elit
26 <em data-cite="takluyver">Thomas</em>. Quisque iaculis ligula ut ipsum mattis viverra.
27
28 * One <cite data-cite="jdfreder">Jonathan</cite>.
29 * Two <cite data-cite="carreau">Matthias</cite>.
30 * Three <cite data-cite="ivanov">Paul</cite>.
31 """
32
33 test_md_parsed = """
34 # My Heading
35
36 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac magna non augue
37 porttitor scelerisque ac id diam \cite{granger}. Mauris elit
38 velit, lobortis sed interdum at, vestibulum vitae libero \cite{fperez}.
39 Lorem ipsum dolor sit amet, consectetur adipiscing elit
40 \cite{takluyver}. Quisque iaculis ligula ut ipsum mattis viverra.
41
42 * One \cite{jdfreder}.
43 * Two \cite{carreau}.
44 * Three \cite{ivanov}.
45 """
46
47 def test_parse_citation():
48 """Are citations parsed properly?"""
49 try:
50 import lxml
51 except ImportError:
52 assert test_md == parse_citation(test_md)
53 else:
54 assert test_md_parsed == parse_citation(test_md)
@@ -68,6 +68,7 b' default_filters = {'
68 68 'strip_math_space': filters.strip_math_space,
69 69 'wrap_text': filters.wrap_text,
70 70 'escape_latex': filters.escape_latex,
71 'parse_citation': filters.parse_citation
71 72 }
72 73
73 74 #-----------------------------------------------------------------------------
@@ -3,4 +3,5 b' from .datatypefilter import *'
3 3 from .highlight import *
4 4 from .latex import *
5 5 from .markdown import *
6 from .strings import * No newline at end of file
6 from .strings import *
7 from .citation import * No newline at end of file
@@ -103,11 +103,11 b' it introduces a new line'
103 103 ((* endblock stream *))
104 104
105 105 ((* block markdowncell scoped *))
106 ((( cell.source | markdown2latex )))
106 ((( cell.source | parse_citation | markdown2latex )))
107 107 ((* endblock markdowncell *))
108 108
109 109 ((* block headingcell scoped -*))
110 ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | markdown2latex )))
110 ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | parse_citation | markdown2latex )))
111 111 ((* endblock headingcell *))
112 112
113 113 ((* block rawcell scoped *))
@@ -127,6 +127,10 b' unknown type ((( cell.type )))'
127 127 ((( super() )))
128 128
129 129 ((* block bodyEnd *))
130
131 ((* block bibliography *))
132 ((* endblock bibliography *))
133
130 134 \end{document}
131 135 ((* endblock bodyEnd *))
132 136 ((* endblock body *))
@@ -192,6 +192,9 b' Note: For best display, use latex syntax highlighting. =))'
192 192 \renewcommand{\indexname}{Index}
193 193 \printindex
194 194
195 ((* block bibliography *))
196 ((* endblock bibliography *))
197
195 198 % End of document
196 199 \end{document}
197 200 ((* endblock bodyEnd *))
@@ -229,7 +232,7 b' Note: For best display, use latex syntax highlighting. =))'
229 232 in IPYNB file titles) do not make their way into latex. Sometimes this
230 233 causes latex to barf. =))
231 234 ((*- endif -*))
232 {((( cell.source | markdown2latex )))}
235 {((( cell.source | parse_citation | markdown2latex )))}
233 236 ((*- endblock headingcell *))
234 237
235 238 %==============================================================================
@@ -239,7 +242,7 b' Note: For best display, use latex syntax highlighting. =))'
239 242 % called since we know we want latex output.
240 243 %==============================================================================
241 244 ((*- block markdowncell scoped-*))
242 ((( cell.source | markdown2latex )))
245 ((( cell.source | parse_citation | markdown2latex )))
243 246 ((*- endblock markdowncell -*))
244 247
245 248 %==============================================================================
General Comments 0
You need to be logged in to leave comments. Login now