include_code.py 2.9 KB

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