Font asset without digest in Ruby on Rails 4 - ruby-on-rails-4

I've got a problem with my font assets being served without digest in production.
As soon as I do rake assets:precompile I get:
5futurebit-webfont-c133dbefd9e1ca208741ed53c7396062.eot
I was trying to link it with font-face in scss with asset-url, asset-path, font-url and font-path but all of them end up outputting path:
/assets/5futurebit-webfont.eot
For now I'm copying assets from /app/assets/fonts straight to /public/assets/ but it doesn't feel like that's the way to do it.

I've been looking at a similar issue and am currently using the non-stupid-digest-assets gem: https://github.com/alexspeller/non-stupid-digest-assets
For more info on how you can use it, see here.
Correct use of non-stupid-digest-assets gem
Now that being said, the link provided by Chris (specifically, https://stackoverflow.com/a/17367264/291640) seems like it may accomplish the same as the gem without the gem itself. I know I need to look into it further.

Make sure you have the exact filename WITH extention name of the font in your font-url declaration like:
Correct:
#font-face{
font-family: 'Sawasdee';
src: font-url('Sawasdee.ttf') format('truetype');
}
Wrong:
#font-face{
font-family: 'Sewasdee';
src: font-url('Sewasdee') format('truetype');
}
My font folder:
fonts
|_ Sewasdee.ttf
|_ Otherfont.ttf

Here is our solution, that is based partially on what Sprocets does. It is working with Rails4. It automatically generates a nondigest version for all assets, that were listed in config.assets.precompile, after precompilation was done.
# lib/tasks/assets_nondigest.rake
require 'fileutils'
namespace "assets:precompile" do
desc "Create nondigest versions of defined assets"
task :nondigest => :environment do
sprocket_task = Sprockets::Rails::Task.new ::Rails.application
assets = ::Rails.application.config.assets.precompile
paths = sprocket_task.index.each_logical_path(assets).to_a +
assets.select { |asset| Pathname.new(asset).absolute? if asset.is_a?(String)}
paths.each do |path|
if asset = sprocket_task.index.find_asset(path)
copy_target = File.join(sprocket_task.output, asset.digest_path)
target = File.join(sprocket_task.output, asset.logical_path)
sprocket_task.logger.info "Writing #{target}"
asset.write_to target
asset.write_to "#{target}.gz" if asset.is_a?(Sprockets::BundledAsset)
end
end
end
end
Rake::Task['assets:precompile'].enhance do
Rake::Task['assets:precompile:nondigest'].invoke
end

Related

CSS files not compiled into app.css as expected in Ember CLI?

Ember CLI docs says about /app/styles folder following:
Contains your stylesheets, whether SASS, LESS, Stylus, Compass, or plain CSS (though only one type is allowed, see Asset Compilation). These are all compiled into app.css.
I have the following files in /app/styles: app.css, one.css, two.css.
I would expect when starting server that in folder /dist/assets there will be file called appName.css and the content would be concatenation of all three files. Instead there is only content of app.css file. So I resolved this with #import in app.css:
#import url("one.css");
#import url("two.css");
That worked with 0.0.46, although not optimal because of more request were made to server. Now I updated to 0.1.1 and files one.css and two.css are no longer copied to /dist/assets folder.
But main question is: How can I achieve the concatenation of all css files in /app/styles folder? Am I missing something basic or are there some commands needed to be included into Brocfile.js?
Updated
Here is the snippet of Brocfile.js showing how we concatenate our CSS files:
var concat = require('broccoli-concat');
var cleanCSS = require('broccoli-clean-css');
var concatenatedCss = concat('app/styles', {
inputFiles: [
'reset.css',
'common.css',
'layout.css',
...
],
outputFile: '/assets/appName.css',
wrapInFunction: false
});
if (app.env === 'production') {
concatenatedCss = cleanCSS(concatenatedCss, {restructuring: false});
}
module.exports = app.toTree([concatenatedCss]);
We manually add files to inputFiles array.
It's known issue with 0.1.1 version: Static css compiler broken (0.1.x regression)
You probably should wait for update.
As for main question, try broccoli-concat.
Now there is this ember-cli-concat add-on available: https://github.com/sir-dunxalot/ember-cli-concat.
Looks super easy to use: https://github.com/sir-dunxalot/ember-cli-concat/wiki/Installation

Does Rails 4.1 still have the asset_path helper?

In the upgrade guide it states
Rails 4.0 removed the ActionController::Base.asset_path option. Use the assets pipeline feature.
I am currently in the process of upgrading from Rails 3.2 to Rails 4.1. In my app I use the select2-rails gem and in my js I add an image for the select menu options:
//mycode.js.erb
function format(image) {
var image_path = "<%= asset_path('" + image.id.toLowerCase() +"') %>"
return "<img class='flag' src='" + image_path + "' />";
}
The above worked in my Rails 3.2 app but I seemed to have broken it with my upgrade to 4.1 and now receive the following error:
Sprockets::FileNotFound - couldn't find file '" + image.id.toLowerCase() +"'
Is the asset_path helper still available in Rails 4.1? If yes, any ideas on where I may have gone wrong?
Update
The code above is in my .js.erb file which allows me to have Ruby code within my js file. This currently works well in my Rails 3.2 project. I am doing this as select2 allows us to format the display of our select menu items as per the below example:
//sample.js
function format(state) {
if (!state.id) return state.text; // optgroup
return "<img class='flag' src='images/flags/" + state.id.toLowerCase() + ".png'/>" + state.text;
}
My understanding was that it is correct usage to use the asset pipeline paths rather than manually adding something like 'assets/images/icons/small'

Gulp-Inject Not Working

I have a simple Gulp build process setup for testing. I've read the documentation many times but I can't seem to get Gulp-inject to inject the scripts I want into an index.html file.
My Gulp file looks like this:
gulp.task('inject1', function() {
return gulp.src('app/index.html')
.pipe(inject(gulp.src('./app/scripts/app.js', {read : false}))) // Not necessary to read the files (will speed up things), we're only after their paths
.pipe(gulp.dest("dist"));
});
gulp.task('inject2', function() {
return gulp.src('app/scripts/**/*.js', {read : false}) // Not necessary to read the files (will speed up things), we're only after their paths
.pipe(inject("./app/index.html"))
.pipe(gulp.dest("./dist"));
});
This is part of my Index.html:
<!-- inject:js -->
<!-- endinject-->
Both of these are copied from the documentation on github.
When I run either of these tasks the console just says "Started 'inject' Finished 'Inject' '
In my ./dist folder it creates an Index.html file but no js files are injected.
I've tried typing in the src and inject properties many different way but no luck. Any idea what I'm doing wrong?
First of all you have a mistake in your endinject tag:
<!-- endinject-->
should be
<!-- endinject -->
This plugin has worked great for me and others in various settings, so the problem is probably in your configuration.
Because when you are using streaming, you cannot be sure which files you pipe along, always try to use a plugin to see exactly what files you are piping. I recommend using gulp-using. Try this to debug your setup:
var debug = require('gulp-debug');
gulp.task('inject2', function() {
return gulp.src('app/scripts/**/*.js', {read : false})
.pipe(debug())
.pipe(inject("./app/index.html"))
.pipe(gulp.dest("./dist"));
});
Also make sure you use the same method to verify that you match your html file as well.
Other than that - it's just trial and error until you understand piping to get just the right files with the correct path.
If gulp-inject isn't injecting any files, that means you didn't pipe them correctly, or your target inject was not correct. The plugin works, and works great for me.
If you need to see an example working gulp file, check out this this gulpfile.js gist
I had the same problem with the following code:
var injectSrc = gulp.src(['./public/css/*.css', '.public/js/*.js'], {read: false});
var injectOptions = {
ignorePath: '/public'
};
var options = {
bowerJson: require('./bower.json'),
directory: './public/lib',
ignorePath: '../../public'
}
gulp.task('inject', function() {
return gulp.src('./src/views/*.html')
.pipe(debug())
.pipe(wiredep(options))
.pipe(debug())
.pipe(inject(injectSrc, injectOptions))
.pipe(debug())
.pipe(gulp.dest('./src/views'));
});
My index.html had the following:
<!--bower:css-->
<!--endbower-->
<!--bower:js-->
<!--endbower-->
<!--inject:css-->
<!--endinject-->
<!--inject:js-->
<!--endinject-->
Click on this link to see what my file structure was.
The inject was creating the css files correctly but not the js files. Also the bower dependencies were working just fine.
Finally I caught the missing '/' in the array passed to gulp.src(). After fixing that to:
var injectSrc = gulp.src(['./public/css/*.css', './public/js/*.js'], {read: false});
it works correctly.

Strange Issue When Minifying CSS via django-pipeline

I'm using django-pipeline to minify my CSS. Everything minifies correctly until I use PipelineCachedStorage so I can get the versioned, cache-busting filenames. I get the following error:
ValueError: The file 'img/glyphicons-halflings.png' could not be found with <pipeline.storage.PipelineCachedStorage object at 0x19069d0>
I've grepped all the files in my project and have found that this PNG is in bootstrap.css, but I am not including that file to be minified. Here's my django-pipeline specific settings:
PIPELINE_CSS = {
'ab': {
'source_filenames': (
'main.css',
'segment-animation.css',
),
'output_filename' : 'ab.css',
}
}
PIPELINE_YUGLIFY_BINARY = '/home/redacted/ts/redacted/node_modules/yuglify/bin/yuglify'
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
Thanks in advance!
EDIT:
new settings for pipeline:
PIPELINE_COMPILERS = (
'pipeline.compilers.less.LessCompiler',
)
PIPELINE_CSS = {
'ab': {
'source_filenames': (
'bootstrap-less/bootstrap.less',
'main.css',
'segment-animation.css',
),
'output_filename' : 'ab.css',
}
}
PIPELINE_YUGLIFY_BINARY = '/home/redacted/ts/redacted/node_modules/yuglify/bin/yuglify'
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
The error isn't entirely related to Pipeline but rather what Django's CachedStaticFilesStorage that PipelineCachedStorage extends. The cached storage will look for file references in your css files and replace url('asset-link') and #import 'resource-link' with the appropriate link to the version with the md5 hash appended to it.
This will turn url('img/glyphicons-halflings.png') into url('img/glyphicons-halflings.<hash>.png'). So if you have asset references in your css files but don't have the underlying assets, the post_process() of CachedStaticFilesStorage is going to throw that error.
You can read more here. I'd recommend to compile the less version of bootstrap with django pipeline and remove the less components that you don't need, such as the icons if you don't want to include the bootstrap icons. Or you can include the appropriate assets.
I've found the django-pipeline-forgiving package resolves this issue with the stock Django CachedStaticFilesStorage / PipelineCachedStorage very nicely

Using Assetic's Css Rewriter outside of Symfony

Let me start by saying I have absolutely no idea what I should be doing because the documentation and available information on Assetic is either limited or Symfony oriented.
Here is my folder structure.
Assetic
+ assets
+ css
+ example.css
+ docs
+ src
+ tests
+ vendor
+ index.php
+ styles.php
Now, I have the following test code. Basically I cloned a clean copy of Assetic and ran composer install. Then I create an index.php file which simply links to my styles.php file with HTMLs <link> tag.
Here is my styles.php
<?php
require 'vendor/autoload.php';
$assetPath = __DIR__.'/assets/css/example.css';
$assetBasePath = __DIR__.'/assets/css';
$asset = new Assetic\Asset\FileAsset($assetPath, array(), $assetBasePath, 'example.css');
header('Content-Type: text/css');
$asset->setTargetPath(__DIR__);
echo $asset->dump(new Assetic\Filter\CssRewriteFilter);
Here is my example.css stylesheet.
body {
background-image: url('../img/background.png');
}
When I load up the styles.php in my browser I get the following output.
url('../img/background.png');
That's the same as the actual CSS. If I use the CSS URI Rewriter from Mr. Clay I get the expected output.
url('/Assetic/assets/img/background.png');
So what am I doing wrong with Assetic? I have no idea what paths I should be passing in and to where.
Thanks.
Just a pretty hard time with it, but finally (after reading the doc. of webassets, python library on which assetic is based) I won over the lack of documentation.
Here you go
<?php
require 'vendor/autoload.php';
$assetPath = __DIR__.'/assets/css/example.css';
$asset = new Assetic\Asset\FileAsset($assetPath, array(new Assetic\Filter\CssRewriteFilter), dirname($assetPath), '/assets/css');
// I assume the 'assets' directory is at the root of your website
header('Content-Type: text/css');
$asset->setTargetPath('/path/to/dumped/asset');
// As above, it's the path to the generated asset from your http root
echo $asset->dump();
I'm not sure to be very clear, so ask if you didn't understand something.