Unable to load CSS using grails rendering plugin - grails

I have a grails 2.4.3 app that uses the rendering 1.0.0 plugin and asset-pipeline:1.9.9. I can successfully generate a PDF from a GSP, but
There is no styling, so it look like garbage
Every CSS reference in the GSP causes java.io.IOException: Stream closed to show up in the logs
When I comment out all CSS references, there are no errors, but it still looks like garbage. I believe the stream closed problem is due to the XHTML parser not being able to load the CSS file. The CSS references look like this
<link rel="stylesheet" href="/Invoicer/assets/invoicer.css?compile=false" />
When I load up that URL in the browser, the CSS file is successfully returned and displayed.
I'm also using Spring Security and thought that maybe it was an authentication issue. I removed all of the filters in Config.groovy, so it looks like this
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/**': ['permitAll']
]
but that did not help. Any ideas? Thanks!

After re-reading the documentation, I noticed this:
The rendering engine resolves all relative links relative to the
grails.serverURL config property.
I figured serverURL would have been set automatically, but it wasn't. I set
grails.serverURL = "http://localhost:9090/${appName}"
in Config.groovy as well as
grails.server.port.http = 9090
in BuildConfig.groovy. It also appears that they layout engine is not getting called, so I had to manually pull in the CSS files:
<asset:stylesheet src="invoicer.css" />

Here is an answer, but it's ugly. I noticed that specifying the full path to the CSS indeed did work:
<link rel="stylesheet" href="http://localhost:9090/Invoicer/assets/bootstrap.css?compile=false" />
Now, since I'm using asset-pipeline, I have to make asset-pipeline use an absolute URL in Config.groovy:
grails.assets.url = "http://localhost:9090/Invoicer/assets/"
Not pretty, but it will work for now.

Related

Grails 2.4.4 SCSS support?

I added sass-grails-asset-pipeline, and in main.gsp I have this:
<asset:stylesheet src="application.css"/>
If I change stylesheets/application.css to stylesheets/application.scss, the GSP produced creates no <link> to request the css. If I do a manual request for http://localhost:8080/my-app/assets/application.css I get a 404.
What's going on? Is there some special undocumented setup to get SCSS working properly?
Make sure you're using a sass-assets plugin that exactly matches your assets-plugin. Mismatching will cause issues.

mod_rewrite not altering LESS file location in the document, direct URL is altered however

I'm trying to pass LESS files over to a PHP compiler via mod_rewrite - when a LESS file is requested, the file should be redirected to the PHP script, passing it's path/name so a CSS file can be spat out.
HTML:
<link rel="stylesheet/less" type="text/css" href="styles/main.less" />
<link rel="stylesheet" type="text/css" href="styles/main.less.css" />
.htaccess:
RewriteEngine On
RewriteBase /v2/
RewriteRule ^([^.]*\.less)$ compilers/lessphp.php?file=$1 [R,L,NC]
Starting out, there is only a .less file.
Refreshing 'http://mydomain.com/v2/' will result in unstyled content. No .css file is created in /styles/.
If I go to 'http://mydomain.com/v2/styles/main.less' I'll be redirected to my PHP compiler 'http://mydomain.com/v2/compilers/lessphp.php?file=styles/main.less', and 'main.less.css' is created as it should within /styles/. Returning to 'http://mydomain.com/v2/', I now have styled content.
Rewrites are only occurring in the URL bar of the browser, not the page of the site.
What am I doing wrong?
EDIT: Is there also a better way to do what I am trying to do?
EDIT2:
/v2/
--index.php
--.htaccess
--/styles/
----main.less
----main.less.css
--/compilers/
----lessphp.php
What happens right now is your browser requests the second link before the compilation is finished and your web server returns 404 because the *.less.css file is not there yet.
A better way to do it would be to have your PHP script output the compilation result (e.g. actual CSS) as a response. Whether or not it also produces a *.less.css file is irrelevant, though you probably do want to cache your CSS output so LESS is not compiled on every request.
In other words:
<link rel="stylesheet/less" type="text/css" href="styles/main.less" /> redirects via mod_rewrite to compilers/lessphp.php?file=styles/mail.less
the above script returns the actual compiled CSS as HTTP response
the second <link> is no longer needed at all
OK, Figured out the issue. Dead simple really.
Playing around with altering extensions and what not, trying to figure out why images would change freely, yet CSS was not, when it struck me that it might have something to do with file type or what not. This is when I noticed the following
<link rel="stylesheet/less" type="text/css" href="styles/main.less" />
rel="stylesheet/less" is the culprit here, and is used by less.js for client side rendering. Replacing simply with rel="stylesheet" like a normal CSS document, Everything. Just. Worked.
Edit: I've written a run through to get Lessphp working properly here

Make Asset Pipeline work with Chrome DevTools Autosave

Chrome DevTools Autosave doesn’t work with Rails Asset Pipeline. The culprit of the problem is in the assets URLs — I cannot decipher the actual file path by its URL. For example, /assets/application.css may refer to either app/assets/stylesheets/application.css, lib/assets/stylesheets/application.css,
or vendor/assets/stylesheets/application.css.
I wonder, how do I change assets URL to one of the following:
/app/assets/stylesheets/application.css (matches exactly actual file path, perfect solution)
/assets/application.css?source_url=app/assets/stylesheets/application.css (introduces source_url query parameter)
I would appreciate any help writing Rails plugin for that.
Update: I filled an issue to sprockets.
I'll try to get the ball rolling, but I'd have to do a lot more to verify or provide a better answer, so I'll mark this answer community wiki. That way others can answer below and or edit this post.
I've had to set up asset pipelining for Sinatra, and generally speaking, in the latest versions of Sprockets (which is used to provide the asset pipelining in Rails) the Sprockets::Asset class has methods to obtain the path and logical path.
I believe Rails uses the asset_path helper to generate the public facing url from the Sprockets class. This in turn appears to use the AssetPaths#compute_public_path instance method. A good first step would be to modify these parts of the code to add a source_url parameter based on your parsing of the source.pathname. This is assuming that source is an instance of Sprockets::Asset in some form or another.
I'm not quite sure how you expect the source to come from but it's already provided by ActionView::Helpers::AssetTagHelper
http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html
image_tag("rails.png")
# => <img alt="Rails" src="http://assets.example.com/images/rails.png?1230601161" />
stylesheet_link_tag("application")
# => <link href="http://assets.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />

grails app root context

I have a test grails app setup with a context of "/testapp". When I add a link in my gsp that references / it does not go to the root of my grails.app.context, but to the root of my grails.serverURL property.
For example given a link with href "/css/main.css"
I would expect that this link would actually look in localhost:8080/testapp/css/main.css instead of localhost:8080/css/main.css
Is there a way that I can get references to / to start at my grails.app.context vs the grails.serverURL?
use the request contextPath value on the page
${request.contextPath}
and then prepend the additional host information if necessary to construct the complete url
the question is how do you add your links into your gsps?
We do things like
<link rel="stylesheet" href="${resource(dir: 'css', file: 'stylesheet1.css')}"/>
and
<g:javascript library="prototype"/>
by using the g:javascript and resource tags and methods, you tell grails to set the path for you...
I suspect you are just putting standard tags in...
goto
http://grails.org/doc/latest/
and, under tags in the left hand nav, look for resource and/or javascript to get an idea (its difficult to link directly in to the docs...:()
I had a similar issue to OP - how to have grails form links that start at the context root and NOT server root?
You can do so using the "uri" attribute for g:link and g:createLink tags. For example:
<g:link uri="/login">login</g:link>
will prefix any context if applicable, and produce the following
login if your app is at the http://server/
login if your app is at http://server/testapp/
Not sure why it's an undocumented attribute in the reference docs, but I found it in the Javadocs - ApplicationTagLib
You should probably be using the resource tag into your grails CSS directory, like mentioned above. However, you can also use the resource method to find the root context of you web application using the same tag:
${resource(uri:'/')}
then just use that string wherever.
And when it comes to elements like stylesheets I'd recommend creating a simple tag that'll do the trick, something along those lines:
class StylesTagLib {
static namespace = "g"
def stylesheet = { args, body ->
out << """<link rel="stylesheet" href="${resource(dir: 'css', file: args.href)}"/>"""
}
}
and later on in your code use it like this:
<g:stylesheet href="main.css"/>
Obviously you can fiddle with the conventions (should I use a predefined folder? should I add the .css extension automatically? stuff like that) but the general idea is to hide the ugliness behind a nicely defined tag.

Anyone have good complete examples of using sitemesh and layouts in Grails 1.2?

I had a grails 1.1 app working where keyword and description meta tags were dynamically generated. There was a change in how that works in 1.2, but I cannot found good documentation. I've tried numerous ways to make it work. No matter what I do the resultant html gets something like
<meta name="keywords"/>" />
instead of the actual keywords. The extra tags there are not a typo on my part. So it also creates a bug in my rendered html.
In Grails 1.2, there's a performance optimized integration to Sitemesh. You can use the old implementation if you specify grails.views.gsp.sitemesh.preprocess = false in Config.groovy.
There are several issues in Grails JIRA related to meta tags :
http://jira.codehaus.org/browse/GRAILS-5605
http://jira.codehaus.org/browse/GRAILS-5598
http://jira.codehaus.org/browse/GRAILS-5696
Some of them will be fixed in Grails 1.2.1 .
I have had problems in 1.2 with meta tags dynamically generates and found that the problems happened when the quote was followed by a $. If I put a space between the quote and the $ it worked like
<meta name="keywords" value=" ${keywords}"/>
May or may not be your problem...

Resources