Rails 3.1 Asset Pipeline Precompiling fails with asset_path wrong arguments - ruby-on-rails-3.1

Day one of dealing with Rails 3.1 asset pipelines and defeated!
Here is the latest in a long line of errors thrown out by the assets:precompile on the production machine:
wrong number of arguments (1 for 2) for 'asset_path'
This happens on the application.css file (which I think is the first one it is trying).
This is the contents of my application.css
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*= require_tree .
*/
.account-badge
{
background-color: #B94A48 !important
}
.centered {
float: none;
margin-left: auto;
margin-right: auto;
}
.container[role="main"] {
padding-bottom: 300px;
}
.page-footer {
border-top: 1px solid #EEEEEE;
padding-top: 17px;
}
Might be important to mention that I'm using twitter-bootstrap-rails in a brand new app (not upgrade)

Take a look at your bootstrap_and_overrides.css.less file, which gets included by sprockets (*= require_tree) of your application.css file.
I guess the error is located by including the #iconSpritePath or the #iconWhiteSpritePath.
Edit:
The method needs two arguments:
asset-url("rails.png", image) # becomes url(/assets/rails.png)
asset-path("rails.png", image) # becomes "/assets/rails.png"
hope that helps

Related

Svelte giving warning for additional class selector on :global()

I am using SCSS in my sveltekit +layout.svelte file to create a global stylesheet. I couldn't find a built-in way to make a global stylesheet so I resorted to just using :global(). This is the code I used:
:global(:where(p, .content)) {
$size: 1rem;
&:not(:last-child) {
margin-block-end: #{$line-height}rem;
}
&.dropcap::first-letter {
$line-count: 2;
font-size: calc($size * (1 + ($line-count * $line-height)));
float: left;
line-height: 0;
vertical-align: middle;
clear: both;
}
}
(note: :where() is used because :global() doesn't support multiple selectors)
The first rule of &:not works fine, but the second rule of &.dropcap shows a warning in the terminal of unused selector (the only content that will match it would go in the <slot /> of layout) and it gets removed from the css output. When I use &:global(.dropcap) svelte also includes the second :global() in the css output. How do I make svelte not remove the css?
The :global() might not propagate inward, you may have to add it everywhere.
For global stylesheets it usually is easier to import them in the <script> along the lines of:
import '../styles/sheet.scss';
This requires the build to be set up to handle such imports, SvelteKit uses Vite which should be able to do this by default.
For some reason, wrapping the problematic selector with :where made the warning goes away (and works).
:global(:where(p, .content)) {
$size: 1rem;
&:not(:last-child) {
margin-block-end: #{$line-height}rem;
}
&:where(.dropcap::first-letter) {
$line-count: 2;
font-size: calc($size * (1 + ($line-count * $line-height)));
float: left;
line-height: 0;
vertical-align: middle;
clear: both;
}
}

Laravel mix - Change production CSS output options

I am trying to change the CSS output style in webpack.mix.js, however it only seems to affect the Development build. How do I apply outpoutStyle options to the Production build?
Here, is my code in the webpack.mix.js file, changing the value of "outputstyle" only affects the Development build.
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css', {
outputStyle : 'expanded'
})
.copy(`resources/images`, `public/images`, false);
laravel-mix: version 5.0.4
sass-loader: version 7.1.0
EDIT - Additional Information:
The problem I'm trying to solve is that my code works fine with a developer build, but then goes pear-shaped when I run a production build. I suspect it has something to do with how the production build takes something like this:
.selector-1 {
background-color: green;
color: red;
}
.selector-2 {
background-color: blue;
color: red;
}
and compiles it to this:
.selector-1 {
background-color: green;
}
.selector-1, .selector-2 {
color: red;
}
.selector-2 {
background-color: blue;
}
In my case, that's undesirable behavior and I believe it's causing scoping issues with my CSS Custom Properties. The compiled code is thousands of lines long so I haven't been able to pinpoint the exact problem - but I notice the development build doesn't do that and everything works fine.
Basically, I’ve got something like this, which I’m using for theming:
:root {
—theme-base: red;
}
.theme-green {
—theme-base: green;
}
everything works fine in Dev mode… but in Prod some of the elements are inheriting the wrong colour value.
So turns out the specific CSS you're trying to output is quite key. From private messaging you I found out it's to do with borders, and your original code is this:
.selector-1 {
border-top-width: 2px;
border-top-style: solid;
border-color: get-color(base, body);
}
In production mode that compiles to
.selector-1 {
border-color: var(--color-base-body)
}
.selector-1 {
border-top: 2px solid;
}
The problem is that if those border properties are in different class selectors, even though they're the same the browser doesn't know what to do with it. We need a way to have all of the relevant border properties in one selectors. Like so:
.selector-1 {
border: 2px solid get-color(base, body);
border-width: 2px 0 0;
}
That compiles to
.u-border-top-2 {
border: solid var(--color-base-body);
border-width: 2px 0 0;
}
...which renders correctly in the browser.
I'm not sure if this is a bug in sass-loader or if a new version fixes it - on first view it looks like the correct behaviour but the cases of borders not so much.

Iterate over theme-variable files in SCSS

I want to create different css-themes for a WordPress theme by using theme setup files. The setup (simplified) would be as following:
/themes/_theme1.scss
/themes/_theme2.scss
/components/_file1.scss
/components/_file2.scss
/theme.scss
The idea is to enable easy theming by adding a class to the body of the document like .theme-theme1 or .theme-theme2. In the files _theme#.scss I want to define variables like text colour, font sizes and so on. In _file#.scss the actual styles are defined.
My question now is, how to iterate over the theme setup files while filling up the files.scss.
Sample idea, Background colour:
body {
###foreach themefile###
&.theme# {
background-color: $background-color;
}
###/foreach###
}
I know how to do this with only one theme available in the resulting CSS file, but I want to make ALL themes available in the resulting CSS. Feel free to ask more details as I am not sure if I explain me right.
Is there a way to create this stylesheet via some kind of foreach loops through variables in theme files or does it have to be done with extra scss-rules per theme file?
This is somewhat possible using a combo of #import with a #mixin to generate the styles. This method should produce minimal repeated code.
Here's how we'll setup the files.
- scss
- themes
- _theme1.scss
- _theme2.scss
- _theme.scss
- styles.scss
The _ prefix on some of the files prevent them from being compiled into CSS to keep our build nice and clean. Now let's go through the contents of the files:
_theme1.scss
$theme-name: 'theme1';
$primary-color: red;
$primary-font-size: 24px;
_theme2.scss
$theme-name: 'theme2';
$primary-color: blue;
$primary-font-size: 12px;
This is an oversimplified example but should give the basic idea. Each theme file will contain only variables.
_theme.scss
#mixin themestyle() {
body.#{$theme-name} {
p {
color: $primary-color;
font-size: $primary-font-size;
}
.bordered {
border: 3px solid $primary-color;
}
}
}
The themestyle mixin will contain all the styles for each theme, using the variables from the /themes/_theme*.scss files. The body.#{$theme-name} will create a selector like body.theme1 or body.theme2, depending on the current value of the $theme-name variable.
In this demo I'm styling on a p tag but this could easily be extended to all elements/selectors for your site. The important thing to remember is all styles need to be inside the body.#{$theme-name} selector.
Now the final, and least DRY part. The styles.scss file will import each theme file then call the themestyle mixin to generate the styles for each theme.
styles.scss
#import 'themes/theme';
/* Theme 1 Styles */
#import 'themes/theme1';
#include themestyles();
/* Theme 2 Styles */
#import 'themes/theme2';
#include themestyles();
The repeated #import/#include is required because it's not possible to #import within a loop or mixin, or this could be optimized a bit more.
Once styles.scss is compiled the output will be:
/* Theme 1 Styles */
body.theme1 p {
color: red;
font-size: 24px; }
body.theme1 .bordered {
border: 3px solid red; }
/* Theme 2 Styles */
body.theme2 p {
color: blue;
font-size: 12px; }
body.theme2 .bordered {
border: 3px solid blue; }
These themes can now be implemented by adding a class to the body tag, like <body class="theme1"> or <body class="theme1">.
Here's a Cloud9 project showing the setup.

SCSS/SASS Not loading custom styles

Dove into SASS this morning for the first time, and I am impressed with the potential...but I am having a slight issue.
(Using Gumby Responsive framework)
So far, I can't seem to get the _custom.scss to compile with everything else.
// Your custom SCSS should be written here...
$color: #0066a6;
body{
background: $color;
}
I added the above to the _custom.scss, went to the command prompt, typed "compass compile" and it returned "unchanged sass/gumby.scss"
I also tried "compass compile sass/_custom.scss" and all that did was create a "custom.css" that (of course) was not showing up either.
What am I doing wrong?
By using the _ at the beginning of your stylesheet name, your using a sass partial. That tells sass to not create standalone stylesheet for _custom.scss at compile time.
Remove the partial to make sass create the sheet: ie. rename it to custom.scss
or keep the partial and import it into your main stylesheet with:
#import "custom";
Example, two sheets _reset.scss and base.scss:
/* _reset.scss */
html,
body,
ul,
ol {
margin: 0;
padding: 0;
}
/* base.scss */
#import 'reset';
body {
font-size: 100% Helvetica, sans-serif;
background-color: #efefef;
Here _reset.scss wont be compiled into its own standalone sheet ( because of the partial), but will be included in the base.scss sheet right before the body declartion ( because base.scss isnt a partial). The output would look like this:
/* base.scss */
html,
body,
ul,
ol {
margin: 0;
padding: 0;
}
body {
font-size: 100% Helvetica, sans-serif;
background-color: #efefef;
Make sure your compass configuration is setup correctly. First initiate your project with:
compass create path/to/project --sass-dir=[your_sass_dir]
Then you'll have a config file called config.rb. It should look something like this:
# Location of the theme's resources.
css_dir = "css"
sass_dir = "sass"
fonts_dir = "css/fonts"
extensions_dir = "sass-extensions"
images_dir = "images"
javascripts_dir = "js"
Solution Found
Was the weirdest thing...opened the "gumby.css" (was a last ditch, "i'm getting super peeved" moment) hit select all -> delete -> save -> close
Then headed back to the command prompt, did the 'compass compile' command, and somehow voila...apparently I just needed to delete everything in the original gumby.css before continuing, because then it recreated the css file with the #import partials working.

Rails 3.1 Asset Pipeline and Third Party JS Calendar

I am working on a Rails 3.1 Application, and it contains a third party JS Calendar Picker (jsDatePick). jsDatePick has a whole stack of images that are in images/calendar/img/.
Running rake assets:precompile precompiles them all, but the library still looks for the images in images/calendar/img (not assets/calendar/img). I could change the directory to assets/calendar/img, but it doesn't append the fingerprint hash.
Thoughts on how to resolve an issue like this?
Here is a sample of some of the CSS that goes along with this JS lib:
.JsDatePickBox .boxLeftWall .leftTopCorner{ margin:0; padding:0; width:7px; height:8px; background:url(/assets/calendar/img/boxTopLeftCorner.png) left top no-repeat; overflow:hidden; }
.JsDatePickBox .boxLeftWall .leftBottomCorner{ margin:0; padding:0; width:7px; height:8px; background:url(/assets/calendar/img/boxBottomLeftCorner.png) left top no-repeat; overflow:hidden; }
.JsDatePickBox .boxLeftWall .leftWall{ margin:0; padding:0; width:7px; background:url(/assets/calendar/img/boxSideWallPx.gif) #ffffff left top repeat-y; overflow:hidden; }
While I definitely see a problem here (asset tags should be used, as these images don't exist in the asset folder without the fingerprint hash), some of the images I am specifically looking for are not in any CSS file in the application. I'm looking now to determine where they are being called.
It looks like the other images are applied via the javascript. Here is an example:
if (parseInt(aDayDiv.getAttribute("isToday")) == 1){
this.setC(aDayDiv, "dayDownToday");
aDayDiv.style.background = "url(" + this.oConfiguration.imgPath + this.oConfiguration.cellColorScheme + "_dayDown.gif) left top no-repeat";
} else {
this.setC(aDayDiv, "dayDown");
aDayDiv.style.background = "url(" + this.oConfiguration.imgPath + this.oConfiguration.cellColorScheme + "_dayDown.gif) left top no-repeat";
}
The oConfiguration.imgPath is defined as such:
g_jsDatePickImagePath = "/assets/calendar/img/";
this.oConfiguration.imgPath = (g_jsDatePickImagePath.length != null) ? g_jsDatePickImagePath : "/images/calendar/img/";
Thank you for your help.
The answer is to upgrade to Rails 3.1.1+ (I upgraded to rails 3.1.2) and the issue is resolved by Rails running rake assets:precompile:nondigest which results in nondigested versions of assets.

Resources