Browse Source

Creole reader: add source code highlighting support.

Correct typo.
Julien Enselme 10 years ago
parent
commit
3a804aec12
2 changed files with 56 additions and 5 deletions
  1. 10 4
      creole_reader/Readme.md
  2. 46 1
      creole_reader/creole_reader.py

+ 10 - 4
creole_reader/Readme.md

@@ -1,7 +1,7 @@
 # Creole Reader
 
 This plugins allows you to write your posts using the wikicreole syntax. Give to
-these files the creole extension. The medata are between `<<header>> <</header>>`
+these files the creole extension. The metadata are between `<<header>> <</header>>`
 tags.
 
 ## Dependency
@@ -9,7 +9,9 @@ This plugin relies on [python-creole](https://pypi.python.org/pypi/python-creole
 `pip install python-creole`
 
 ## Syntax
-Use ** for strong, // for emphasis, one = for 1st level titles.
+Use ** for strong, // for emphasis, one = for 1st level titles. Please use the
+following macro for code highlighting:
+`<<code ext=".file_extension">> <</code>>`
 
 For the complete syntax, look at: http://www.wikicreole.org/
 
@@ -24,12 +26,16 @@ date: 2013-12-12
 = Title 1
 == Title 2
 
-Some nice texte with **strong** and //emphasis//.
+Some nice text with **strong** and //emphasis//.
 
 * A nice list
-** With subelements
+** With sub-elements
 * Python
 
+<<code ext=".py">>
+print("Hello World")
+<</code>>
+
 # An ordered list
 # A second item
 ```

+ 46 - 1
creole_reader/creole_reader.py

@@ -21,6 +21,14 @@ try:
 except ImportError:
     creole = False
 
+try:
+    from pygments import lexers
+    from pygments.formatters import HtmlFormatter
+    from pygments import highlight
+    PYGMENTS = True
+except:
+    PYGMENTS = False
+
 class CreoleReader(readers.BaseReader):
     enabled = creole
 
@@ -39,6 +47,42 @@ class CreoleReader(readers.BaseReader):
                 self._metadata[name] = self.process_metadata(name, value)
         return u''
 
+    def _no_highlight(self, text):
+        html = u'\n<pre><code>{}</code></pre>\n'.format(text)
+        return html
+
+    def _get_lexer(self, source_type, code):
+        try:
+            return lexers.get_lexer_by_name(source_type)
+        except:
+            return lexers.guess_lexer(code)
+
+    def _get_formatter(self):
+        formatter = HtmlFormatter(lineos = True, encoding='utf-8',
+                                  style='colorful', outencoding='utf-8',
+                                  cssclass='pygments')
+        return formatter
+
+    def _parse_code_macro(self, ext, text):
+        if not PYGMENTS:
+            return self._no_highlight(text)
+
+        try:
+            source_type = ''
+            if '.' in ext:
+                source_type = ext.strip().split('.')[1]
+            else:
+                source_type = ext.strip()
+        except IndexError:
+            source_type = ''
+        lexer = self._get_lexer(source_type, text)
+        formatter = self._get_formatter()
+
+        try:
+            return highlight(text, lexer, formatter).decode('utf-8')
+        except:
+            return self._no_highlight(text)
+
     # You need to have a read method, which takes a filename and returns
     # some content and the associated metadata.
     def read(self, source_path):
@@ -46,7 +90,8 @@ class CreoleReader(readers.BaseReader):
 
         self._metadata = {}
         with pelican_open(source_path) as text:
-            content = creole2html(text, macros={'header': self._parse_header_macro})
+            content = creole2html(text, macros={'header': self._parse_header_macro,
+                                            'code': self._parse_code_macro})
         return content, self._metadata
 
 def add_reader(readers):