A fork of hyde, the static site generation. Some patches will be pushed upstream.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

109 lines
3.5 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. Contains classes to combine files into one
  4. """
  5. from fnmatch import fnmatch
  6. from hyde.model import Expando
  7. from hyde.plugin import Plugin
  8. class CombinePlugin(Plugin):
  9. """
  10. To use this combine, the following configuration should be added
  11. to meta data::
  12. combine:
  13. files:
  14. - ns1.*.js
  15. - ns2.*.js
  16. where: top
  17. remove: yes
  18. `files` is a list of resources (or just a resource) that should be
  19. combined. Globbing is performed. `where` indicate where the
  20. combination should be done. This could be `top` or `bottom` of the
  21. file. `remove` tell if we should remove resources that have been
  22. combined into the resource.
  23. """
  24. def __init__(self, site):
  25. super(CombinePlugin, self).__init__(site)
  26. def _combined(self, resource):
  27. """
  28. Return the list of resources to combine to build this one.
  29. """
  30. try:
  31. config = resource.meta.combine
  32. except AttributeError:
  33. return [] # Not a combined resource
  34. try:
  35. files = config.files
  36. except AttributeError:
  37. raise AttributeError("No resources to combine for [%s]" % resource)
  38. if type(files) is str:
  39. files = [ files ]
  40. # Grab resources to combine
  41. resources = []
  42. for r in resource.node.resources:
  43. for f in files:
  44. if fnmatch(r.name, f):
  45. resources.append(r)
  46. break
  47. if not resources:
  48. self.logger.debug("No resources to combine for [%s]" % resource)
  49. return []
  50. return sorted(resources, key=lambda r: r.name)
  51. def begin_site(self):
  52. """
  53. Initialize the plugin and search for the combined resources
  54. """
  55. for node in self.site.content.walk():
  56. for resource in node.resources:
  57. resources = self._combined(resource)
  58. if not resources:
  59. continue
  60. # Build depends
  61. if not hasattr(resource, 'depends'):
  62. resource.depends = []
  63. resource.depends.extend(
  64. [r.relative_path for r in resources
  65. if r.relative_path not in resource.depends])
  66. # Remove combined resources if needed
  67. if hasattr(resource.meta.combine, "remove") and \
  68. resource.meta.combine.remove:
  69. for r in resources:
  70. self.logger.debug(
  71. "Resource [%s] removed because combined" % r)
  72. r.is_processable = False
  73. def text_resource_complete(self, resource, text):
  74. """
  75. When generating a resource, add combined file if needed.
  76. """
  77. resources = self._combined(resource)
  78. if not resources:
  79. return
  80. where = "bottom"
  81. try:
  82. where = resource.meta.combine.where
  83. except AttributeError:
  84. pass
  85. if where not in [ "top", "bottom" ]:
  86. raise ValueError("%r should be either `top` or `bottom`" % where)
  87. self.logger.debug(
  88. "Combining %d resources for [%s]" % (len(resources),
  89. resource))
  90. if where == "top":
  91. return "".join([r.source.read_all() for r in resources] + [text])
  92. else:
  93. return "".join([text] + [r.source.read_all() for r in resources])