import base64 import filetype import os import re from .file import generate_breadcrumbs, sanitize_file_name, tree_join from .page import Page from .tree import safe_join def bytes_to_content(file_bytes): if not file_bytes: return (None, 'empty') try: text = file_bytes.decode('utf-8') return (text, 'text') except UnicodeError: if filetype.is_image(file_bytes): # TODO: Refer to the static file once that's implemented. img = base64.b64encode(file_bytes) return (img.decode('utf-8'), 'image') return (None, None) class FilePage(Page): def __init__(self, out_dir, name, commit, file_name, file_path, content_subdir): tree = safe_join(commit.tree, file_path) super(FilePage, self).__init__('file.md', out_dir, os.path.join(tree_join(commit, file_path), sanitize_file_name(file_name, tree.blobs) + '.md'), name, content_subdir) self.commit = commit self.file_name = file_name self.file_path = file_path self.tree = tree def read_file(self): return self.tree.join(self.file_name).data_stream.read() def context(self): file_bytes = self.read_file() content, file_type = bytes_to_content(file_bytes) backtick_max = 2 if file_type == 'text': if self.file_name.lower().endswith('.md'): backtick_max = -1 content = re.sub(r'(`{3,}\W)', r'\\\1', content) else: matches = re.findall('`+', content) backtick_max = max(max(len(match) for match in matches) if matches else 0, backtick_max) return { 'backtick_max': backtick_max + 1, 'breadcrumbs': generate_breadcrumbs(self.content_subdir, self.commit, os.path.join(self.file_path, self.file_name), self.tree.blobs), 'content': content, 'content_subdir': self.content_subdir, 'file_extension': os.path.splitext(self.file_name)[1].lstrip('.'), 'title': self.name + ': ' + self.file_name, 'this_commit': self.commit, 'type': file_type }