include_code.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """
  2. Include Code Tag
  3. ----------------
  4. This implements a Liquid-style video tag for Pelican,
  5. based on the octopress video tag [1]_
  6. Syntax
  7. ------
  8. {% include_code path/to/code [Title text] %}
  9. The "path to code" is relative to the code path in
  10. the content directory (TODO: allow this to be set in configs).
  11. Example
  12. -------
  13. {% include_code myscript.py %}
  14. This will import myscript.py from content/downloads/code/myscript.py
  15. and output the contents in a syntax highlighted code block inside a figure,
  16. with a figcaption listing the file name and download link.
  17. The file link will be valid only if the 'code' directory is listed
  18. in the STATIC_PATHS setting, e.g.:
  19. STATIC_PATHS = ['images', 'code']
  20. [1] https://github.com/imathis/octopress/blob/master/plugins/include_code.rb
  21. """
  22. import re
  23. import os
  24. from .mdx_liquid_tags import LiquidTags
  25. SYNTAX = "{% include_code /path/to/code.py [lang:python] [title] %}"
  26. FORMAT = re.compile(r"""^(?:\s+)?(?P<src>\S+)(?:\s+)?(?:(?:lang:)(?P<lang>\S+))?(?:\s+)?(?P<title>.+)?$""")
  27. @LiquidTags.register('include_code')
  28. def include_code(preprocessor, tag, markup):
  29. markup = markup.strip()
  30. title = None
  31. lang = None
  32. src = None
  33. match = FORMAT.search(markup)
  34. if match:
  35. argdict = match.groupdict()
  36. title = argdict['title']
  37. lang = argdict['lang']
  38. src = argdict['src']
  39. if not src:
  40. raise ValueError("Error processing input, "
  41. "expected syntax: {0}".format(SYNTAX))
  42. # TODO: make this directory a configurable setting
  43. code_dir = 'code'
  44. code_path = os.path.join('content', code_dir, src)
  45. if not os.path.exists(code_path):
  46. return "File {0} could not be found".format(code_path)
  47. code = open(code_path).read()
  48. if title:
  49. title = "{0} {1}".format(title, os.path.basename(src))
  50. else:
  51. title = os.path.basename(src)
  52. url = '/{0}/{1}/{2}'.format('static', code_dir, src)
  53. open_tag = ("<figure class='code'>\n<figcaption><span>{title}</span> "
  54. "<a href='{url}'>download</a></figcaption>".format(title=title,
  55. url=url))
  56. close_tag = "</figure>"
  57. # store HTML tags in the stash. This prevents them from being
  58. # modified by markdown.
  59. open_tag = preprocessor.configs.htmlStash.store(open_tag, safe=True)
  60. close_tag = preprocessor.configs.htmlStash.store(close_tag, safe=True)
  61. source = (open_tag
  62. + '\n\n ' + '\n '.join(code.split('\n')) + '\n\n'
  63. + close_tag + '\n')
  64. return source
  65. #----------------------------------------------------------------------
  66. # This import allows image tag to be a Pelican plugin
  67. from liquid_tags import register