Last active
December 15, 2015 10:59
-
-
Save milankinen/5249593 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.tunkkaus | |
import org.grails.plugin.resource.ResourceMeta | |
import org.grails.plugin.resource.ResourceProcessor | |
import org.grails.plugin.resource.mapper.MapperPhase; | |
import org.grails.plugin.resource.module.ModuleBuilder | |
import org.springframework.util.AntPathMatcher | |
/** | |
* We are using prefix '_' because we want that this resource mapper | |
* is FIRST mapper of the processing chain. Sorting is done by name | |
* so '_' prefix gives us advantage compared to other mappers. | |
* | |
*/ | |
class _MultiModuleResourceMapper { | |
private static final String MULTIPLE_RESOURCES_PREFIX = "/__multiModule__" | |
private static long declaredResourcesNum = 0 | |
static defaultIncludes = [ '**/*.coffee', '**/*.js', '**/*.handlebars' ] | |
static String getResourcePrefix() { "${MULTIPLE_RESOURCES_PREFIX}.${declaredResourcesNum++}/" } | |
static boolean isMultipleResourceFile(String uri) { uri?.startsWith(MULTIPLE_RESOURCES_PREFIX) } | |
static String getOriginalURI(String uri) { uri?.replaceFirst(MULTIPLE_RESOURCES_PREFIX + '\\.\\d+/', '/') } | |
private static boolean canBeRenamed(String filepath) { | |
if(filepath.startsWith(MULTIPLE_RESOURCES_PREFIX)) return false | |
// behaviour can be modified by chancing defaultIncludes | |
def matcher = new AntPathMatcher() | |
return defaultIncludes.find { matcher.match(it, filepath) } != null | |
} | |
/** | |
* Call this from resources.groovy! This modifies resources plugin methods | |
* so that they support multiple resource definitions inside multiple modules. | |
*/ | |
static void enable() { | |
def origResource = ModuleBuilder.metaClass.getMetaMethod("resource", [Object] as Object[]) | |
def origGetURL = ResourceProcessor.metaClass.getMetaMethod("getOriginalResourceURLForURI", [Object] as Object[]) | |
assert origResource != null && origGetURL != null | |
// override modulebuilder's resource function to apply a unique prefix | |
// because file will have an unique prefix, then it is interpreted as | |
// "new" file for resources plugin | |
ModuleBuilder.metaClass.resource = { attrs -> | |
if (attrs instanceof String) { | |
if (canBeRenamed(attrs)) { | |
attrs = resourcePrefix + attrs | |
} | |
} else if (attrs instanceof Map && attrs.url instanceof String) { | |
if (canBeRenamed(attrs.url)) { | |
attrs.url = resourcePrefix + attrs.url | |
} | |
} | |
origResource.invoke(delegate, attrs) | |
} | |
// this method is called before resource processing chain begins | |
// this gets the file handle to the original resource. Since we have | |
// added a prefix, the actual file is never found unless we tweak this | |
// method a little bit to transform the modified filename back to the | |
// original one (just for this method) | |
ResourceProcessor.metaClass.getOriginalResourceURLForURI { uri -> | |
if (isMultipleResourceFile(uri)) { | |
uri = getOriginalURI(uri) | |
} | |
return origGetURL.invoke(delegate, uri) | |
} | |
} | |
// using first possible mapper phase | |
def phase = MapperPhase.GENERATION | |
def map(resource, config) { | |
def url = resource?.actualUrl | |
// now we can process the resource whatever we want. Let's just change | |
// resource's URLs back to the original file's, so that later processors | |
// can deal with right file. | |
if (isMultipleResourceFile(url)) { | |
url = getOriginalURI(url) | |
resource.actualUrl = resource.originalUrl = resource.sourceUrl = url | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment