import pygments.lexers import pygments.formatters.html import pygments.styles.monokai import os import jinja2 import errno import util import markdown # need to define templates before importing format (which depends on them) templates = {} templates_dir = os.path.join(os.path.dirname(__file__), 'templates') for name in os.listdir(templates_dir): with file(os.path.join(templates_dir, name)) as f: templates[name] = jinja2.Template(f.read()) import format class Generator: def __init__(self, source_directory, output_directory, ignore_paths, site44, custom_types): self.source_directory = source_directory self.output_directory = output_directory self.ignore_paths = ignore_paths self.site44 = site44 self.use_extensions = not site44 self.custom_types = custom_types def generate(self): if self.site44: with file(os.path.join(self.output_directory, 'mimetypes.site44.txt'), 'wt') as f: f.write('/raw/**/* text/plain\n/file/**/* text/html\n') for d in ['tree', 'file', 'raw']: os.mkdir(os.path.join(self.output_directory, d)) self.css_file = os.path.join(self.output_directory, 'styles.css') with file(self.css_file, 'wt') as f: f.write(templates['css'].render(pygments_styles = pygments.formatters.html.HtmlFormatter(style=pygments.styles.monokai.MonokaiStyle).get_style_defs('.highlight'))) for dirpath, dirnames, filenames in os.walk(self.source_directory): # weed out ignored paths dirnames[:] = filter(lambda dirname: os.path.abspath(os.path.join(dirpath, dirname)) not in self.ignore_paths and not dirname.startswith('.'), dirnames) reldir = os.path.relpath(dirpath, self.source_directory) if reldir != '.': os.mkdir(os.path.join(self.output_directory, 'tree', reldir)) for d in ['file', 'raw']: try: os.mkdir(os.path.join(self.output_directory, d, reldir)) except OSError, e: if e.errno != errno.EEXIST: raise e included_files = [] for filename in filenames: file_path = os.path.join(dirpath, filename) print 'Processing %s' % file_path if util.is_binary(file_path): continue included_files.append(filename) self.generate_file(file_path) self.generate_index(dirpath, dirnames, filenames, included_files) def generate_file(self, source_file): relpath = os.path.relpath(source_file, self.source_directory) output_file = os.path.join(self.output_directory, 'file', relpath) output_raw = os.path.join(self.output_directory, 'raw', relpath) html_extension = self.use_extensions and '.html' or '' raw_extension = self.use_extensions and '.txt' or '' relcss = os.path.relpath(self.css_file, os.path.dirname(output_file)).replace('\\', '/') formatter = format.CodeShowFormatter(encoding='utf-8', style=pygments.styles.monokai.MonokaiStyle, cssfile=relcss, noclobber_cssfile=True, title=relpath.replace('\\', '/'), raw_path=os.path.relpath(output_raw, os.path.dirname(output_file)).replace('\\', '/')+raw_extension, use_extensions=self.use_extensions) name_for_lexer = source_file extension = os.path.splitext(source_file)[1].lstrip('.').lower() if extension in self.custom_types: name_for_lexer = '.' + self.custom_types[extension] try: lexer = pygments.lexers.get_lexer_for_filename(name_for_lexer) except: lexer = pygments.lexers.TextLexer() with file(source_file) as infile: code = infile.read().decode('utf-8-sig') with file(output_file+html_extension, 'wt') as outfile: pygments.highlight(code, lexer, formatter, outfile) with file(output_raw+raw_extension, 'wt') as outfile: outfile.write(code.encode('utf-8')) def generate_index(self, dirpath, dirnames, filenames, included_files): reldir = os.path.relpath(dirpath, self.source_directory) if reldir == '.': index_path = os.path.join(self.output_directory, 'index.html') else: index_path = os.path.join(self.output_directory, 'tree', reldir + '.html') readme = None is_markdown = False if os.path.isfile(os.path.join(dirpath, 'readme.md')): is_markdown = True with file(os.path.join(dirpath, 'readme.md')) as f: readme = markdown.markdown(f.read()) else: filename = None for name in ['readme', 'readme.txt']: if os.path.isfile(os.path.join(dirpath, name)): filename = name if filename is not None: with file(os.path.join(dirpath, filename)) as f: formatter = format.CodeShowFormatter(encoding='utf-8', style=pygments.styles.monokai.MonokaiStyle, nowrap=True) readme = pygments.highlight(f.read().decode('utf-8-sig'), pygments.lexers.TextLexer(), formatter) with file(index_path, 'wt') as f: f.write(templates['directory'].render( reldir = reldir != '.' and reldir.replace('\\', '/') + '/' or '', relroot = os.path.relpath(self.output_directory, os.path.dirname(index_path)).replace('\\', '/'), relcss = os.path.relpath(self.css_file, os.path.dirname(index_path)).replace('\\', '/'), directories = [(name, not os.path.islink(os.path.join(dirpath, name))) for name in dirnames], files = [(name, name in included_files) for name in filenames], readme = readme, is_markdown = is_markdown, use_extensions = self.use_extensions )) def generate(source_directory, output_directory, ignore_paths, site44): Generator(source_directory, output_directory, ignore_paths, site44).generate()