Permalink
Browse files

Added landslide (v1.0.1)

  • Loading branch information...
1 parent 1d351a0 commit 048172aa1bc9198ce7b394bafcc0610f476e1fbc @mitotic committed Sep 25, 2012
No changes.
Oops, something went wrong.
@@ -0,0 +1,188 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2010 Adam Zapletal
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import re
+import htmlentitydefs
+import pygments
+import sys
+import utils
+
+from pygments.lexers import get_lexer_by_name
+from pygments.formatters import HtmlFormatter
+
+
+class Macro(object):
+ """Base class for Macros. A Macro aims to analyse, process and eventually
+ alter some provided HTML contents and to provide supplementary
+ informations to the slide context.
+ """
+ options = {}
+
+ def __init__(self, logger=sys.stdout, embed=False, options=None):
+ self.logger = logger
+ self.embed = embed
+ if options:
+ if not isinstance(options, dict):
+ raise ValueError(u'Macro options must be a dict instance')
+ self.options = options
+
+ def process(self, content, source=None):
+ """Generic processor (does actually nothing)"""
+ return content, []
+
+
+class CodeHighlightingMacro(Macro):
+ """This Macro performs syntax coloration in slide code blocks using
+ Pygments.
+ """
+ code_blocks_re = re.compile(
+ r'(<pre.+?>(<code>)?\s?!(\w+?)\n(.*?)(</code>)?</pre>)',
+ re.UNICODE | re.MULTILINE | re.DOTALL)
+
+ html_entity_re = re.compile('&(\w+?);')
+
+ def descape(self, string, defs=None):
+ """Decodes html entities from a given string"""
+ if defs is None:
+ defs = htmlentitydefs.entitydefs
+ f = lambda m: defs[m.group(1)] if len(m.groups()) > 0 else m.group(0)
+ return self.html_entity_re.sub(f, string)
+
+ def process(self, content, source=None):
+ code_blocks = self.code_blocks_re.findall(content)
+ if not code_blocks:
+ return content, []
+
+ classes = []
+ for block, void1, lang, code, void2 in code_blocks:
+ try:
+ lexer = get_lexer_by_name(lang)
+ except Exception:
+ self.logger(u"Unknown pygment lexer \"%s\", skipping"
+ % lang, 'warning')
+ return content, classes
+
+ if 'linenos' not in self.options or self.options['linenos'] =='no':
+ self.options['linenos'] = False
+
+ formatter = HtmlFormatter(linenos=self.options['linenos'],
+ nobackground=True)
+ pretty_code = pygments.highlight(self.descape(code), lexer,
+ formatter)
+ content = content.replace(block, pretty_code, 1)
+
+ return content, [u'has_code']
+
+
+class EmbedImagesMacro(Macro):
+ """This Macro extracts images url and embed them using the base64
+ algorithm.
+ """
+ def process(self, content, source=None):
+ classes = []
+
+ if not self.embed:
+ return content, classes
+
+ images = re.findall(r'<img\s.*?src="(.+?)"\s?.*?/?>', content,
+ re.DOTALL | re.UNICODE)
+
+ source_dir = os.path.dirname(source)
+
+ for image_url in images:
+ encoded_url = utils.encode_image_from_url(image_url, source_dir)
+
+ if not encoded_url:
+ self.logger(u"Failed to embed image \"%s\"" % image_url, 'warning')
+ return content, classes
+
+ content = content.replace(u"src=\"" + image_url,
+ u"src=\"" + encoded_url, 1)
+
+ self.logger(u"Embedded image %s" % image_url, 'notice')
+
+ return content, classes
+
+
+class FixImagePathsMacro(Macro):
+ """This Macro replaces html image paths with fully qualified absolute
+ urls.
+ """
+ relative = False
+
+ def process(self, content, source=None):
+ classes = []
+
+ if self.embed:
+ return content, classes
+ base_path = utils.get_path_url(source, self.options.get('relative'))
+ base_url = os.path.split(base_path)[0]
+
+ images = re.findall(r'<img.*?src="(?!http://)(.*?)".*/?>', content,
+ re.DOTALL | re.UNICODE)
+
+ for image in images:
+ full_path = os.path.join(base_url, image)
+
+ content = content.replace(image, full_path)
+
+ return content, classes
+
+
+class FxMacro(Macro):
+ """This Macro processes fx directives, ie adds specific css classes
+ named after what the parser found in them.
+ """
+ def process(self, content, source=None):
+ classes = []
+
+ fx_match = re.search(r'(<p>\.fx:\s?(.*?)</p>\n?)', content,
+ re.DOTALL | re.UNICODE)
+ if fx_match:
+ classes = fx_match.group(2).split(u' ')
+ content = content.replace(fx_match.group(1), '', 1)
+
+ return content, classes
+
+
+class NotesMacro(Macro):
+ """This Macro processes Notes."""
+ def process(self, content, source=None):
+ classes = []
+
+ new_content = re.sub(r'<p>\.notes:\s?(.*?)</p>',
+ r'<p class="notes">\1</p>', content)
+
+ if content != new_content:
+ classes.append(u'has_notes')
+
+ return new_content, classes
+
+
+class QRMacro(Macro):
+ """This Macro generates a QR Code with Google Chart API."""
+ def process(self, content, source=None):
+ classes = []
+
+ new_content = re.sub(r'<p>\.qr:\s?(\d*?)\|(.*?)</p>',
+ r'<p class="qr"><img src="http://chart.apis.google.com/chart?chs=\1x\1&cht=qr&chl=\2&chf=bg,s,00000000&choe=UTF-8" alt="QR Code" /></p>',
+ content)
+
+ if content != new_content:
+ classes.append(u'has_qr')
+
+ return new_content, classes
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright 2010 Adam Zapletal
+#
+# Modified by R. Saravanan to work with GraphTerm (2012)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+
+try:
+ import jinja2, pygments
+except ImportError:
+ print >> sys.stderr, "To use landslide, please install the following python packages using easy_install (or other methods):\n jinja2, pygments, markdown (for *.md files), docutils (for *.rst files)"
+ sys.exit(1)
+
+try:
+ from landslide import generator
+except ImportError:
+ import generator
+
+from optparse import OptionParser
+
+
+def _parse_options():
+ """ Parses ``landslide`` args options.
+ """
+
+ parser = OptionParser(
+ usage="%prog [options] input.md ...",
+ description="Generates an HTML5 or PDF "
+ "slideshow from Markdown or other formats",
+ epilog="Note: PDF export requires the `prince` program: "
+ "http://princexml.com/")
+
+ parser.add_option(
+ "-c", "--copy-theme",
+ action="store_true",
+ dest="copy_theme",
+ help="Copy theme directory into current presentation source directory",
+ default=False)
+
+ parser.add_option(
+ "-b", "--debug",
+ action="store_true",
+ dest="debug",
+ help="Will display any exception trace to stdout",
+ default=False)
+
+ parser.add_option(
+ "-d", "--destination",
+ dest="destination_file",
+ help="The path to the to the destination file: .html or "
+ ".pdf extensions allowed (default: presentation.html)",
+ metavar="FILE",
+ default="presentation.html")
+
+ parser.add_option(
+ "-e", "--encoding",
+ dest="encoding",
+ help="The encoding of your files (defaults to utf8)",
+ metavar="ENCODING",
+ default="utf8")
+
+ parser.add_option(
+ "-i", "--embed",
+ action="store_true",
+ dest="embed",
+ help="Embed stylesheet and javascript contents, "
+ "base64-encoded images in presentation to make a "
+ "standalone document",
+ default=False)
+
+ parser.add_option(
+ "-l", "--linenos",
+ type="choice",
+ choices=generator.VALID_LINENOS,
+ dest="linenos",
+ help="How to output linenos in source code. Three options availables: "
+ "no (no line numbers); "
+ "inline (inside <pre> tag); "
+ "table (lines numbers in another cell, copy-paste friendly)",
+ default="inline",
+ )
+
+ parser.add_option(
+ "-o", "--direct-output",
+ action="store_true",
+ dest="direct",
+ help="Prints the generated HTML code to stdout; won't work with PDF "
+ "export",
+ default=False)
+
+ parser.add_option(
+ "-q", "--quiet",
+ action="store_false",
+ dest="verbose",
+ help="Won't write anything to stdout (silent mode)",
+ default=False)
+
+ parser.add_option(
+ "-r", "--relative",
+ action="store_true",
+ dest="relative",
+ help="Make your presentation asset links relative to current pwd; "
+ "This may be useful if you intend to publish your html "
+ "presentation online.",
+ default=False,
+ )
+
+ parser.add_option(
+ "-t", "--theme",
+ dest="theme",
+ help="A theme name, or path to a landlside theme directory",
+ default='default')
+
+ parser.add_option(
+ "-v", "--verbose",
+ action="store_true",
+ dest="verbose",
+ help="Write informational messages to stdout (enabled by default)",
+ default=True)
+
+ parser.add_option(
+ "-x", "--extensions",
+ dest="extensions",
+ help="Comma-separated list of extensions for Markdown",
+ default='',
+ )
+
+ (options, args) = parser.parse_args()
+
+ if not args:
+ parser.print_help()
+ sys.exit(1)
+
+ return options, args[0]
+
+
+def log(message, type):
+ """Basic logger, print output directly to stdout and errors to stderr.
+ """
+ (sys.stdout if type == 'notice' else sys.stderr).write(message + "\n")
+
+
+def run(input_file, options):
+ """ Runs the Generator using parsed options.
+ """
+ options.logger = log
+ generator.Generator(input_file, **options.__dict__).execute()
+
+
+def main():
+ """ Main program entry point.
+ """
+ options, input_file = _parse_options()
+
+ if (options.debug):
+ run(input_file, options)
+ else:
+ try:
+ run(input_file, options)
+ except Exception, e:
+ sys.stderr.write("Error: %s\n" % e)
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
Oops, something went wrong.

0 comments on commit 048172a

Please sign in to comment.