PostRenderer.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import re
  2. from pygments import highlight
  3. from pygments.lexers import get_lexer_by_name
  4. from pygments.formatters import HtmlFormatter
  5. import mistune
  6. from mistune import Renderer, InlineGrammar, InlineLexer, BlockGrammar, BlockLexer
  7. from helpers.filesystem_helper import get_all_files_in_folder
  8. from FileReader import FileReader
  9. class PostRenderer:
  10. def __init__(self):
  11. super(PostRenderer, self).__init__()
  12. self.highlight_renderer = HighlightRenderer()
  13. self.meta_data_inline_lexer = MetaDataInlineLexer(self.highlight_renderer) # the lexer needs to know the renderer to call its meta_data function
  14. self.meta_data_inline_lexer.enable_meta_data() # don't forget to enable it!
  15. self.markdown = mistune.Markdown(
  16. renderer=self.highlight_renderer,
  17. inline=self.meta_data_inline_lexer,
  18. escape=False,
  19. )
  20. def render_posts_from(self, directory_path):
  21. markdown_extensions = ['markdown', 'md', 'mdown']
  22. file_list = get_all_files_in_folder(directory_path, file_extensions=markdown_extensions)
  23. file_reader = FileReader()
  24. html_contents = []
  25. for file_name in file_list:
  26. markdown_content = file_reader.read_file(directory_path + file_name)
  27. post_content = self.markdown(markdown_content)
  28. # html_contents.append('<article>{post_content}</article><p class="post-separator">––––––––––––––––––––––––</p>'.format(post_content=post_content))
  29. html_contents.append('<article>{post_content}</article><p class="post-separator">––––</p>'.format(post_content=post_content))
  30. complete_html_content = ''.join(html_contents)
  31. return complete_html_content
  32. class HighlightRenderer(mistune.Renderer):
  33. def block_code(self, code, lang):
  34. if not lang:
  35. return '\n<pre><code>{code}</code></pre>\n'.format(
  36. code=mistune.escape(code)
  37. )
  38. lexer = get_lexer_by_name(lang, stripall=True)
  39. formatter = HtmlFormatter(
  40. linenos='table',
  41. linenospecial=4,
  42. lineseparator='<br>',
  43. lineanchors='code-line-link',
  44. linespans='code-line-span',
  45. anchorlinenos='lineno-line'
  46. )
  47. return highlight(code, lexer, formatter)
  48. def meta_data(self, attribute, value):
  49. if attribute.lower() == 'title':
  50. return '<h1 class="post-title">{title}</h1>'.format(title=value)
  51. elif attribute.lower() == 'author':
  52. return '<p class="post-author"><em>Author: {author}</em></p>'.format(author=value)
  53. elif attribute.lower() == 'date':
  54. return '<p class="post-date"><em>Date: {date}</em></p>'.format(date=value)
  55. else:
  56. return '<p class="post-meta-data"><em>{attribute}: {value}</em></p>'.format(attribute=attribute, value=value)
  57. class MetaDataInlineLexer(InlineLexer):
  58. def enable_meta_data(self):
  59. self.rules.meta_data = re.compile(
  60. r'(%\s*)'
  61. r'(?P<attribute>.*)'
  62. r'(\s*:\s*)'
  63. r'(?P<value>.*)'
  64. r'(\s*)'
  65. )
  66. self.default_rules.insert(3, 'meta_data')
  67. def output_meta_data(self, match):
  68. attribute = match.group('attribute')
  69. value = match.group('value')
  70. return self.renderer.meta_data(attribute, value)