/hyde/ext/plugins/stylus.py

http://github.com/hyde/hyde · Python · 117 lines · 73 code · 17 blank · 27 comment · 16 complexity · ef9b20e0505d59a0eaa54a12f458c71d MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. """
  3. Less css plugin
  4. """
  5. from hyde.plugin import CLTransformer
  6. from hyde.fs import File
  7. import re
  8. import subprocess
  9. class StylusPlugin(CLTransformer):
  10. """
  11. The plugin class for less css
  12. """
  13. def __init__(self, site):
  14. super(StylusPlugin, self).__init__(site)
  15. def begin_site(self):
  16. """
  17. Find all the styl files and set their relative deploy path.
  18. """
  19. for resource in self.site.content.walk_resources():
  20. if resource.source_file.kind == 'styl':
  21. new_name = resource.source_file.name_without_extension + ".css"
  22. target_folder = File(resource.relative_deploy_path).parent
  23. resource.relative_deploy_path = target_folder.child(new_name)
  24. def begin_text_resource(self, resource, text):
  25. """
  26. Replace @import statements with {% include %} statements.
  27. """
  28. if not resource.source_file.kind == 'styl':
  29. return
  30. import_finder = re.compile(
  31. '^\\s*@import\s+(?:\'|\")([^\'\"]*)(?:\'|\")\s*\;?\s*$',
  32. re.MULTILINE)
  33. def import_to_include(match):
  34. """
  35. Converts a css import statement to include statemnt.
  36. """
  37. if not match.lastindex:
  38. return ''
  39. path = match.groups(1)[0]
  40. afile = File(File(resource.source_file.parent.child(path)).fully_expanded_path)
  41. if len(afile.kind.strip()) == 0:
  42. afile = File(afile.path + '.styl')
  43. ref = self.site.content.resource_from_path(afile.path)
  44. if not ref:
  45. try:
  46. include = self.settings.args.include
  47. except AttributeError:
  48. include = False
  49. if not include:
  50. raise self.template.exception_class(
  51. "Cannot import from path [%s]" % afile.path)
  52. else:
  53. ref.is_processable = False
  54. return "\n" + \
  55. self.template.get_include_statement(ref.relative_path) + \
  56. "\n"
  57. return '@import "' + path + '"\n'
  58. text = import_finder.sub(import_to_include, text)
  59. return text
  60. @property
  61. def defaults(self):
  62. """
  63. Returns `compress` if not in development mode.
  64. """
  65. try:
  66. mode = self.site.config.mode
  67. except AttributeError:
  68. mode = "production"
  69. defaults = {"compress":""}
  70. if mode.startswith('dev'):
  71. defaults = {}
  72. return defaults
  73. @property
  74. def plugin_name(self):
  75. """
  76. The name of the plugin.
  77. """
  78. return "stylus"
  79. def text_resource_complete(self, resource, text):
  80. """
  81. Save the file to a temporary place and run stylus compiler.
  82. Read the generated file and return the text as output.
  83. Set the target path to have a css extension.
  84. """
  85. if not resource.source_file.kind == 'styl':
  86. return
  87. stylus = self.app
  88. source = File.make_temp(text)
  89. target = source
  90. supported = [("compress", "c"), ("include", "I")]
  91. args = [unicode(stylus)]
  92. args.extend(self.process_args(supported))
  93. args.append(unicode(source))
  94. try:
  95. self.call_app(args)
  96. except subprocess.CalledProcessError, e:
  97. raise self.template.exception_class(
  98. "Cannot process %s. Error occurred when "
  99. "processing [%s]" % (stylus.name, resource.source_file))
  100. return target.read_all()