Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

adding support to compile less files inside a plugin #7

Open
wants to merge 3 commits into from

8 participants

@jvalde

Hi Paul,

Thanks for your contribution this plugin made our work possible,

we are working using a plugin oriented architecture where we have a core plugin which provides common resources as templates, css, javascripts and images, the plugin works great when using it on the main application (the less files live on the main app) however it fails when the less files live in a plugin, because it can't work out the right path,

I have added support for this case, when you got a plugin that uses lesscss-resources that then is then installed on another application,

There is something dodgy that I don't like on code that I committed and it's the way that I used to find out whether the resource lives on a plugin I had to rely on the sourcePath, as far as I've seen the object ResourceMeta does not provide a pluginName property (the name of the plugin passed in the resource for instance "resource url:[dir:'css', file:'basic.less', plugin:'basic-core'], bundle:'bundle_style'") which would be ideal for this case,

Please check the changes and let me know your thoughts,

@jvalde

I have added support to inline pluglins. This is when the less files to be compiled live on an inline plugin

@benatwork99

I've also run into this issue. Some brief testing last week seemed to indicate that the above code still works, but doesn't work for a binary plugin.

@jvalde

hi Ben,

I've made some extra changes that might have fixed the problem you're having, however I have not pushed them to github yet, I will do it tomorrow as I'm not currently at my office.

@longwa

I assume this change would fix a problem we are having trying to use the bootstrap plugin. Namely, we want to install the plugin for the majority of the bootstrap files and then just override the few that need customizing in our application. Also, we need to import some of the mixins for use in our own custom LESS. Right now, the plugin doesn't seem to be able to resolve things inside the plugin when doing an import.

@eplarson

+1 vote for integrating this - I'm having the same issue. less files are compiled when I run my plugin standalone, but as soon as use my plugin in another application, I get nothing.

Interestingly, the exact same issue affects the other less resources plugin (http://grails.org/plugin/less-resources)

@csherstan

+1, need a fix for this. The other less-resources plugin has it's own issues, so right now I can't use either.

@jvalde

Hi all,

There was an issue for the version 0.6 of this plugin, where it was unable to find less files when they lived inside a plugin, this version attempts to fix this problem however as far as I've tested the newest version of this plugin solves the issue mentioned above.

Another issue I was having which isn't fixed on this version nor on the newest version of this plugin is the inability of importing mixins from other plugins inside less files. In our case we have a core plugin which holds base js, less, shell|templates (gsp), then we have other plugins or apps which make use of those base files. A cool feature that we needed in order to get the most flavor out of less was the ability to import seamlessly mixins in less files from the core plugin. So if some of you are facing the same situation let me know and I will commit a version which solves this case with some examples,

Hope this helps

@mpccolorado

Which plugin does it work right now? yours? or Paul Fairless's plugin? Can you commit your fix to solve these issues? I was struggling with this problem with this and less-resources plugin for a few days and I don't know what else to do...
Thanks a lot!

Martín Caballero

@jvalde

both this version and the newest one (Paul Fairless's) solve the problem of having the less files living inside a plugin however neither of them allow you to import mixins from a plugin to either an app or another plugin.

I explain a little bit further the case that is not supported,

for example you have plugin A which contains a less file to be imported:

_toBeImported.less

.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

Then you have another plugin b which contains
basic.less

@import "_toBeImported";

#menu a {
  color: #111;
  .bordered;
}
.post a {
  color: red;
  .bordered;
}

I have a version that solves both cases but it still in progress however we are using it on a production site and works like a charm, will commit it this week, you may find it useful

@mpccolorado

Thanks for the response!
I look forward for your submit...
Regards!
+1

@longwa

jvalde,
+1 for the import fix, itwould be much appreciated. I spent a bit of time looking at the fix but now I've decided to wait for you :)

It stinks that both less plugins have issues that prevent them doing what we need right now. Namely, I just want to use bootstrap as a plugin and import mixins, etc. to use in my application stylesheets.

@eplarson

Here's how to replicate the problem I'm seeing. Do the following (in grails 2.0.1, at least):

  1. grails create-plugin lesstestplugin
  2. Add a Resources artifact that looks like this:
    modules = {

        mystyle {
            resource url:'less/test.less',attrs:[rel: "stylesheet/less", type:'css']
            resource url:'less/test2.less',attrs:[rel: "stylesheet/less", type:'css']
        }

    }
  1. Create the two files mentioned in the 'mystyle' module
  2. Create an index.gsp file under views and import the module:
<html>
<head>
  <title></title>

    <r:require module="mystyle" />

    <r:layoutResources />
</head>
<body>

    <r:layoutResources />
</body>
</html>
  1. Note that the two files are compiled to css and imported correctly:
<link href="/lesstestplugin/static/less/test_less.css" type="text/css" media="screen, projection" rel="stylesheet" />
<link href="/lesstestplugin/static/less/test2_less.css" type="text/css" media="screen, projection" rel="stylesheet" />
  1. Now create a new app: grails create-app lesstest
  2. Import your plugin in to the app
// in BuildConfig.groovy, above dependency resolution closure:
grails.plugin.location.'lesstestplugin' = "../lesstestplugin"
  1. In the app's main.gsp, import the module previously defined in lesstestplugin :
<r:require module="mystyle"/>
  1. Note that the two files are imported, but NOT compiled to css. Result:
<link href="/lesstest/static/less/test.less" type="text/css" media="screen, projection" rel="stylesheet/less" />
<link href="/lesstest/static/less/test2.less" type="text/css" media="screen, projection" rel="stylesheet/less" />

Is there anything wrong with this example? I don't think I can break it down to be much simpler. I've tried many other avenues, and the bottom line is that I can't get less files to compile if they're in a plugin, period.

@benatwork99

I tested version 1.3.0.3 of this plugin and could not get LESS resources within a binary plugin to be compiled, I tested defining the resource both within the plugin and within the web-app which uses the plugin. If I changed the plugin definition in BuildConfig.groovy to be inline (which AFAIK is the same as a source plugin) then the resources could be compiled.

jvalde, I don't see a recent commit from you, but you mentioned above that you had some code which might fix this issue?

@cweekly

+1 @jvalde or anyone else who can help, please fix the ability to import .less files from plugins!
I'm using grails 2.0.0 + twitter-bootstrap plugin v2.1.1 + lesscss-resources plugin v1.3.0.3.

I need to selectively override small parts of twitter-bootstrap (e.g. parts of variables.less), but @import just doesn't work in my custom .less files, the twitter-bootstrap resources (provided by the plugin) just can't be found.

So far, blocked on ability to make these plugins work together for what seems like a vanilla / standard use case.

Thanks very much in advance for any help!

@selera

I would like to hear from anyone who has news about getting less resources accessible to a grails app from a binary plugin.

@jvalde - do you have anything to share?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
2  LesscssResourcesGrailsPlugin.groovy
@@ -1,6 +1,6 @@
class LesscssResourcesGrailsPlugin {
// the plugin version
- def version = "0.6"
+ def version = "0.6.1-SNAPSHOT"
// the version or versions of Grails the plugin is designed for
def grailsVersion = "1.3.5 > *"
// the other plugins this plugin depends on
View
34 grails-app/resourceMappers/LesscssResourceMapper.groovy
@@ -1,6 +1,8 @@
import com.asual.lesscss.LessEngine
import com.asual.lesscss.LessException
import org.grails.plugin.resource.mapper.MapperPhase
+import org.codehaus.groovy.grails.plugins.GrailsPluginUtils
+import grails.util.PluginBuildSettings
/**
* @author Paul Fairless
@@ -9,12 +11,16 @@ import org.grails.plugin.resource.mapper.MapperPhase
*/
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
import org.codehaus.groovy.grails.commons.GrailsResourceUtils
+import org.springframework.util.AntPathMatcher
class LesscssResourceMapper {
def phase = MapperPhase.GENERATION // need to run early so that we don't miss out on all the good stuff
static defaultExcludes = ['**/*.js','**/*.png','**/*.gif','**/*.jpg','**/*.jpeg','**/*.gz','**/*.zip']
static String LESS_FILE_EXTENSION = '.less'
+ static String PLUGIN_PREFIX = '/plugins/'
+ static final PATH_MATCHER = new AntPathMatcher()
+
def map(resource, config){
File originalFile = resource.processedFile
@@ -50,6 +56,32 @@ class LesscssResourceMapper {
}
private File getOriginalFileSystemFile(String sourcePath) {
- new File(GrailsResourceUtils.WEB_APP_DIR + sourcePath);
+ def resourceFile
+ if(isPlugin(sourcePath)){
+ def pluginFullName = getPluginFullName(sourcePath)
+ def resourcePath = getResourceRelativePath(pluginFullName, sourcePath)
+
+ def ourPluginInfo = GrailsPluginUtils.getPluginInfos().find{pluginInfo -> pluginFullName.contains(pluginInfo.name)}
+ resourceFile = new File(ourPluginInfo.pluginDir.path + '/' + GrailsResourceUtils.WEB_APP_DIR + '/' + resourcePath)
+
+ if(resourceFile.exists()){
+ return resourceFile
+ }
+ }
+
+ return new File(GrailsResourceUtils.WEB_APP_DIR + sourcePath)
+ }
+
+ private getPluginFullName(sourcePath){
+ def pluginMap = PATH_MATCHER.extractUriTemplateVariables(PLUGIN_PREFIX + '{plugin}/**', sourcePath)
+ pluginMap.get('plugin')
+ }
+
+ private getResourceRelativePath(pluginName, sourcePath){
+ PATH_MATCHER.extractPathWithinPattern(PLUGIN_PREFIX+ pluginName +'/**', sourcePath)
+ }
+
+ private isPlugin(String original){
+ PATH_MATCHER.match(PLUGIN_PREFIX + '**', original)
}
}
Something went wrong with that request. Please try again.