Repository: plone/Products.CMFPlone

Issue:
CSS bundles generation breaks background images relative urls
This is a bug related to PR #1300.



Discussion:

Resolving patch:
diff --git a/Products/CMFPlone/resources/browser/combine.py b/Products/CMFPlone/resources/browser/combine.py
--- a/Products/CMFPlone/resources/browser/combine.py
+++ b/Products/CMFPlone/resources/browser/combine.py
@@ -1,18 +1,20 @@
-from zExceptions import NotFound
 from Acquisition import aq_base
 from datetime import datetime
 from plone.registry.interfaces import IRegistry
 from plone.resource.file import FilesystemFile
 from plone.resource.interfaces import IResourceDirectory
 from Products.CMFPlone.interfaces import IBundleRegistry
-from Products.CMFPlone.interfaces.resources import (
-    OVERRIDE_RESOURCE_DIRECTORY_NAME,
-)
+from Products.CMFPlone.interfaces.resources import OVERRIDE_RESOURCE_DIRECTORY_NAME  # noqa
 from StringIO import StringIO
+from zExceptions import NotFound
 from zope.component import getUtility
 from zope.component import queryUtility
 
+import logging
+import re
+
 PRODUCTION_RESOURCE_DIRECTORY = "production"
+logger = logging.getLogger(__name__)
 
 
 def get_production_resource_directory():
@@ -24,6 +26,8 @@ def get_production_resource_directory():
         production_folder = container[PRODUCTION_RESOURCE_DIRECTORY]
     except NotFound:
         return "%s/++unique++1" % PRODUCTION_RESOURCE_DIRECTORY
+    if 'timestamp.txt' not in production_folder:
+        return "%s/++unique++1" % PRODUCTION_RESOURCE_DIRECTORY
     timestamp = production_folder.readFile('timestamp.txt')
     return "%s/++unique++%s" % (
         PRODUCTION_RESOURCE_DIRECTORY, timestamp)
@@ -38,7 +42,12 @@ def get_resource(context, path):
         if overrides.isFile(filepath):
             return overrides.readFile(filepath)
 
-    resource = context.unrestrictedTraverse(path)
+    try:
+        resource = context.unrestrictedTraverse(path)
+    except NotFound:
+        logger.warn(u"Could not find resource {0}. You may have to create it first.".format(path))  # noqa
+        return
+
     if isinstance(resource, FilesystemFile):
         (directory, sep, filename) = path.rpartition('/')
         return context.unrestrictedTraverse(directory).readFile(filename)
@@ -71,7 +80,10 @@ def write_js(context, folder, meta_bundle):
         IBundleRegistry, prefix="plone.bundles", check=False)
     for bundle in bundles.values():
         if bundle.merge_with == meta_bundle and bundle.jscompilation:
-            resources.append(get_resource(context, bundle.jscompilation))
+            resource = get_resource(context, bundle.jscompilation)
+            if not resource:
+                continue
+            resources.append(resource)
 
     fi = StringIO()
     for script in resources:
@@ -87,7 +99,18 @@ def write_css(context, folder, meta_bundle):
         IBundleRegistry, prefix="plone.bundles", check=False)
     for bundle in bundles.values():
         if bundle.merge_with == meta_bundle and bundle.csscompilation:
-            resources.append(get_resource(context, bundle.csscompilation))
+            css = get_resource(context, bundle.csscompilation)
+            if not css:
+                continue
+            (path, sep, filename) = bundle.csscompilation.rpartition('/')
+            # Process relative urls:
+            # we prefix with current resource path any url not starting with
+            # '/' or http: or data:
+            css = re.sub(
+                r"""(url\(['"]?(?!['"]?([a-z]+:|\/)))""",
+                r'\1%s/' % path,
+                css)
+            resources.append(css)
 
     fi = StringIO()
     for script in resources:


Test patch: