##// END OF EJS Templates
Only check for node on first call, not on import.
Jonathan Frederic -
Show More
@@ -1,131 +1,139 b''
1 """Markdown filters
1 """Markdown filters
2 This file contains a collection of utility filters for dealing with
2 This file contains a collection of utility filters for dealing with
3 markdown within Jinja templates.
3 markdown within Jinja templates.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Stdlib imports
18 # Stdlib imports
19 import os
19 import os
20 import subprocess
20 import subprocess
21 import warnings
21 from io import TextIOWrapper, BytesIO
22 from io import TextIOWrapper, BytesIO
22
23
23 # IPython imports
24 # IPython imports
24 from IPython.nbconvert.utils.pandoc import pandoc
25 from IPython.nbconvert.utils.pandoc import pandoc
25 from IPython.nbconvert.utils.exceptions import ConversionException
26 from IPython.nbconvert.utils.exceptions import ConversionException
26 from IPython.utils.process import get_output_error_code
27 from IPython.utils.process import get_output_error_code
27 from IPython.utils.py3compat import cast_bytes
28 from IPython.utils.py3compat import cast_bytes
28 from IPython.utils.version import check_version
29 from IPython.utils.version import check_version
29
30
30 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
31 # Functions
32 # Functions
32 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
33 marked = os.path.join(os.path.dirname(__file__), "marked.js")
34 marked = os.path.join(os.path.dirname(__file__), "marked.js")
35 _node = None
34
36
35 __all__ = [
37 __all__ = [
36 'markdown2html',
38 'markdown2html',
37 'markdown2html_pandoc',
39 'markdown2html_pandoc',
38 'markdown2html_marked',
40 'markdown2html_marked',
39 'markdown2latex',
41 'markdown2latex',
40 'markdown2rst',
42 'markdown2rst',
41 ]
43 ]
42
44
43 class NodeJSMissing(ConversionException):
45 class NodeJSMissing(ConversionException):
44 """Exception raised when node.js is missing."""
46 """Exception raised when node.js is missing."""
45 pass
47 pass
46
48
47 def markdown2latex(source):
49 def markdown2latex(source):
48 """Convert a markdown string to LaTeX via pandoc.
50 """Convert a markdown string to LaTeX via pandoc.
49
51
50 This function will raise an error if pandoc is not installed.
52 This function will raise an error if pandoc is not installed.
51 Any error messages generated by pandoc are printed to stderr.
53 Any error messages generated by pandoc are printed to stderr.
52
54
53 Parameters
55 Parameters
54 ----------
56 ----------
55 source : string
57 source : string
56 Input string, assumed to be valid markdown.
58 Input string, assumed to be valid markdown.
57
59
58 Returns
60 Returns
59 -------
61 -------
60 out : string
62 out : string
61 Output as returned by pandoc.
63 Output as returned by pandoc.
62 """
64 """
63 return pandoc(source, 'markdown', 'latex')
65 return pandoc(source, 'markdown', 'latex')
64
66
67 def markdown2html(source):
68 """Convert a markdown string to HTML"""
69 global _node
70 if _node is None:
71 # prefer md2html via marked if node.js >= 0.9.12 is available
72 # node is called nodejs on debian, so try that first
73 _node = 'nodejs'
74 if not _verify_node(_node):
75 _node = 'node'
76 if not _verify_node(_node):
77 warnings.warn( "Node.js 0.9.12 or later wasn't found.\n" +
78 "Nbconvert will try to use Pandoc instead.")
79 _node = False
80 if not _node:
81 return markdown2html_pandoc(source)
82 else:
83 return markdown2html_marked(source)
84
65 def markdown2html_pandoc(source):
85 def markdown2html_pandoc(source):
66 """Convert a markdown string to HTML via pandoc"""
86 """Convert a markdown string to HTML via pandoc"""
67 return pandoc(source, 'markdown', 'html', extra_args=['--mathjax'])
87 return pandoc(source, 'markdown', 'html', extra_args=['--mathjax'])
68
88
69 def markdown2html_marked(source, encoding='utf-8'):
89 def markdown2html_marked(source, encoding='utf-8'):
70 """Convert a markdown string to HTML via marked"""
90 """Convert a markdown string to HTML via marked"""
71 command = [node_cmd, marked]
91 command = [_node, marked]
72 try:
92 try:
73 p = subprocess.Popen(command,
93 p = subprocess.Popen(command,
74 stdin=subprocess.PIPE, stdout=subprocess.PIPE
94 stdin=subprocess.PIPE, stdout=subprocess.PIPE
75 )
95 )
76 except OSError as e:
96 except OSError as e:
77 raise NodeJSMissing(
97 raise NodeJSMissing(
78 "The command '%s' returned an error: %s.\n" % (" ".join(command), e) +
98 "The command '%s' returned an error: %s.\n" % (" ".join(command), e) +
79 "Please check that Node.js is installed."
99 "Please check that Node.js is installed."
80 )
100 )
81 out, _ = p.communicate(cast_bytes(source, encoding))
101 out, _ = p.communicate(cast_bytes(source, encoding))
82 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
102 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
83 return out.rstrip('\n')
103 return out.rstrip('\n')
84
104
85 def markdown2rst(source):
105 def markdown2rst(source):
86 """Convert a markdown string to LaTeX via pandoc.
106 """Convert a markdown string to LaTeX via pandoc.
87
107
88 This function will raise an error if pandoc is not installed.
108 This function will raise an error if pandoc is not installed.
89 Any error messages generated by pandoc are printed to stderr.
109 Any error messages generated by pandoc are printed to stderr.
90
110
91 Parameters
111 Parameters
92 ----------
112 ----------
93 source : string
113 source : string
94 Input string, assumed to be valid markdown.
114 Input string, assumed to be valid markdown.
95
115
96 Returns
116 Returns
97 -------
117 -------
98 out : string
118 out : string
99 Output as returned by pandoc.
119 Output as returned by pandoc.
100 """
120 """
101 return pandoc(source, 'markdown', 'rst')
121 return pandoc(source, 'markdown', 'rst')
102
122
103 def _verify_node(cmd):
123 def _verify_node(cmd):
104 """Verify that the node command exists and is at least the minimum supported
124 """Verify that the node command exists and is at least the minimum supported
105 version of node.
125 version of node.
106
126
107 Parameters
127 Parameters
108 ----------
128 ----------
109 cmd : string
129 cmd : string
110 Node command to verify (i.e 'node')."""
130 Node command to verify (i.e 'node')."""
111 try:
131 try:
112 out, err, return_code = get_output_error_code([cmd, '--version'])
132 out, err, return_code = get_output_error_code([cmd, '--version'])
113 except OSError:
133 except OSError:
114 # Command not found
134 # Command not found
115 return False
135 return False
116 if return_code:
136 if return_code:
117 # Command error
137 # Command error
118 return False
138 return False
119 return check_version(out.lstrip('v'), '0.9.12')
139 return check_version(out.lstrip('v'), '0.9.12')
120
121 # prefer md2html via marked if node.js >= 0.9.12 is available
122 # node is called nodejs on debian, so try that first
123 node_cmd = 'nodejs'
124 if _verify_node(node_cmd):
125 markdown2html = markdown2html_marked
126 else:
127 node_cmd = 'node'
128 if _verify_node(node_cmd):
129 markdown2html = markdown2html_marked
130 else:
131 markdown2html = markdown2html_pandoc
General Comments 0
You need to be logged in to leave comments. Login now