Inlining data-urls with Stylus and Gulp - css

Currently I have a stylus file that imports another stylus file. This second file uses the URL function like this, and I want it to be inlined (e.g. to a base 64 data-url). However this isn't working when run through my gulp pipeline
lines.styl:
vertical-img = 'vertical.svg';
#import "../tree";
tree.styl
background-image: url(vertical-img)
What I want to get as a result is:
background-image: url('data:image/svg+xml;utf8,<svg>[...]</svg>');
But I get this:
background-image: url("vertical.svg")
And my gulpfile is as follows:
return gulp.src('src/css/*/*.styl')
.pipe(gstylus({
set: ['resolve url']
}))
.pipe(rename(function (file) {
file.dirname = "";
file.extname = ".css";
}))
.pipe(gulp.dest(DEST))
Basically it seems like the 'resolve url' option isn't being passed to stylus. I'm aware that I need it, since it says in the Stylus Docs that:
By default Stylus doesn’t resolve the urls in imported .styl files, so if you’d happen to have a foo.styl with #import "bar/bar.styl" which would have url("baz.png"), it would be url("baz.png") too in a resulting CSS.
But you can alter this behavior by using --resolve-url (or just -r) CLI option to get url("bar/baz.png") in your resulting CSS.

The correct option for image inlining is url (not resolve url) see http://learnboost.github.io/stylus/docs/functions.url.html. To use it in gulp-stylus you should pass url option to options object (see https://github.com/jenius/accord/blob/master/docs/stylus.md#url). For example:
return gulp.src('src/css/*/*.styl')
.pipe(gstylus({
url: { name: 'url', limit: false }
}))
.pipe(rename(function (file) {
file.dirname = "";
file.extname = ".css";
}))
.pipe(gulp.dest(DEST))

Related

Add all CSS files in a folder to nuxt.config

In my Nuxt project I have a folder assets/scss/globals/ with a lot of files which should be globally included.
Now in my nuxt.config file I can only include each file by manually like so:
// Global CSS: https://go.nuxtjs.dev/config-css
css: ['./assets/scss/globals/resets.scss'],
What I would need is something like this:
css: ['./assets/scss/globals/*.scss'],
But this doesn't work.
I have the styled-resources package installed as well for variable and mixin definition and there it works:
styleResources: {
scss: ['./assets/scss/variables/*.scss']
},
But the documentation clearly says to not include styles here:
Do not import actual styles. Use this module only to import variables, mixins, functions (et cetera) as they won't exist in the actual build. Importing actual styles will include them in every component and will also make your build/HMR magnitudes slower. Do not do this!
Is what I try to do any different from what the warning in styled-resources says?
CSS option in nuxt.config.js requires an array of files, If you do not want to specify them manually one by one you can simply create a function that returns them like below
Function in nuxt.config.js or import as a util
const styleFiles = (path) => {
const fs = require('fs')
const files = fs.readdirSync(path)
return files.map((i) => path + i)
}
Then use it like so
css: styleFiles('src/assets/scss/globals'),

gulp-base64 - stop on error

I use gulp as a build system in my web project
I have a number of CSS files (well, actually, LESS, but it does not matter)
I do link image files from my CSS rules in this way:
.my-rule {
background-image: url('/images/kitten.svg');
}
Next, I'm embedding those images as Base-64 into my production CSS files.
That is a gulp task:
var gulp = require("gulp"),
...
base64 = require('gulp-base64');
gulp.task("sass", function () {
return gulp.src(paths.styles)
.pipe(base64())
.pipe(concat("concatedstyles.css"))
.pipe(gulp.dest(paths.webroot + "css"));
});
The problem is:
When I link to non-existing file:
.my-rule {
background-image: url('/images/non-existing-kitten.svg');
}
the build system does not report me about failure.
It just leave this line as is.
So, I'm not aware about error at build time, only at runtime.
I tried to play with .pipe(sass.sync().on("error", sass.logError)), but no luck.
Any advice?

How to switch css file when using Webpack to load css?

I use gulp to compile my sass file to css files, and reference the css file in my html. The project support theme switch. For example, I have 3 css theme files:
red.css
yellow.css
blue.css
I can currently switch the theme css like this:
var styleDom = $('#theme-style');
var newHref = 'styles/themes/' + themeName + '.css';
if (styleDom.attr('href') !== newHref) {
styleDom.attr('href', newHref);
}
Now I want to use webpack to load the css file.
require('styles/themes/red.css');
It seems work well, but I cannot find a way to switch the theme css file now, does anyone have a solution?
Your approach doesn’t need to change. Just use Extract Text plugin to save out the CSS files. You’ll need to make multiple entry points to create multiple CSS files.
OR
More ideally, (the approach I would take) make your CSS switch based on a different html or body class and just change the class. It won’t add much overhead, and it will be a more ideal UX when changing themes.
You'll need to use a combination of webpacks style-loader and file-loader (second example ) and use require.ensure (second example "dynamic imports") to accomplish this:
function switchTheme(name) {
// Remove the current theme stylesheet
// Note: it is important that your theme css always is the last
// <link/> tag within the <head/>
$('head link[rel="stylesheet"]').last().remove();
// Since webpack needs all filePaths at build-time
// you can't dynamically build the filePath
switch(name) {
case 'red':
// With require.ensure, it is possible to tell webpack
// to only load the module (css) when require is actually called
return require.ensure([], function () {
require('style-loader/url!file-loader!styles/themes/red.css');
});
case 'yellow':
return require.ensure([], function () {
require('style-loader/url!file-loader!styles/themes/yellow.css');
});
case 'blue':
return require.ensure([], function () {
require('style-loader/url!file-loader!styles/themes/blue.css');
});
default:
throw new Error('Unknown theme "' + name + '"');
}
}
Then a call like switchTheme('blue') should do the trick.
And you might have to check your current webpack.config.js, in case you already have configured a loader for .css files.

How to set proper base for the input files for gulp-concat-css?

I am using gulp-concat-css to combine a selected list of CSS into one. My project folder structure look like this:
[]Project Folder
gulpfile.js
---[]public
------[]assets
---------[]libs (All bower install libraries such as bootstrap will be placed here)
---------[]css (All my custom CSS including the combined CSS will be placed here)
Now, my gulp task look something like this:
gulp.task('concatcss', function() {
return gulp.src(['public/assets/libs/bootstrap/dist/css/bootstrap.min.css',
'public/assets/libs/angular-motion/dist/angular-motion.min.css',
'public/assets/libs/bootstrap-additions/dist/bootstrap-additions.min.css',
'public/assets/libs/blueimp-file-upload/css/jquery.fileupload.css',
'public/assets/css/mycustom.css'])
.pipe(concatCss("css/all.css").on('error', standardHandler))
.pipe(minifyCss().on('error', standardHandler))
.pipe(gulp.dest('public/assets'));
});
The problem is the final output come with the wrong url rebase. This cause the CSS URL is pointing to the wrong path of files. For example, the original URL from the bootstrap.min.css is url('../fonts/glyphicons-halflings-regular.woff'). Now, the combined CSS come with the URL of url(../../fonts/glyphicons-halflings-regular.woff), which is wrong. It should be url(../libs/bootstrap/dist/fonts/glyphicons-halflings-regular.woff)
According to gulp-concat-css documentation, it says "for a proper import inlining and url rebase, make sure you set the proper base for the input files".
How can I set the proper base for the input files to get the correct url rebase?
You have to set the base as option in gulp.src like this { base: 'public/assets' }:
gulp.task('concatcss', function() {
return gulp.src(['public/assets/libs/bootstrap/dist/css/bootstrap.min.css',
'public/assets/libs/angular-motion/dist/angular-motion.min.css',
'public/assets/libs/bootstrap-additions/dist/bootstrap-additions.min.css',
'public/assets/libs/blueimp-file-upload/css/jquery.fileupload.css',
'public/assets/css/mycustom.css'], { base: 'public/assets' })
.pipe(concatCss("css/all.css").on('error', standardHandler))
.pipe(minifyCss().on('error', standardHandler))
.pipe(gulp.dest('public/assets'));
});

Compass Line Number Comments Not Showing Up with Gulp

I am attempting to make the switch from GruntJS to Gulp and have run into a problem with my Gulp task for processing my SASS files via Compass. The files compile just fine into the single CSS file as they did under my GruntJS implementation, but I am missing the line number comments that show me where the CSS rules come from such as:
/* line 26, ../_components/sass/_base.scss */
The code from my gulpfile.js for the task is:
gulp.task('compass', function() {
gulp.src(sassSources)
.pipe(compass({
comments: true,
sass: '_components/sass',
image: 'builds/dev/images',
style: 'nested'
})
.on('error', gutil.log))
.pipe(gulp.dest('builds/dev/css'))
});
Am I missing something?
Be careful with gulp-compass, it is not a gulp plugin (albeit named so) and has been blacklisted by the Gulp community for quite a while. It does not what Gulp plugins are supposed to do (e.g. it's possible to run them without gulp.src and gulp.dest), and other plugins are already doing its work perfectly fine. One of those plugins is gulp-ruby-sass. This setup might work for you:
var sass = require('gulp-ruby-sass');
gulp.task('compass', function() {
return sass(sassSources, {
compass: true,
lineNumbers: true
}).on('error', gutil.log))
.pipe(gulp.dest('builds/dev/css'))
});
This uses gulp-ruby-sass which is able to run with the compass extension. You see that I activated lineNumbers here to give you said output.
I see from your Gulpfile that you might have some extension requiring some images, I don't know exactly what that does, but if it's mandatory to your setup, you might better call compass directly (the command line tool) using require('child_process').exec(...)
You should add sass_options = { :line_numbers => true } to your config.rb file even if gulp-compass module doesn't support lineNumbers as an option.
important part of config.rb file
css_dir = 'app/assets/style/'
sass_dir = 'app/assets/style/sass/'
images_dir = 'app/assets/image/'
javascripts_dir = 'app/assets/script/'
sass_options = { :line_numbers => true }
And your gulp task should look like this
important part of gulpfile.js file
return gulp.src('./app/assets/style/sass/*.scss')
.pipe(plugins.compass({
config_file: './config.rb', // if you don't use a config file , you should start using immediately
css: './app/assets/style/',
sass: './app/assets/style/sass/',
image: './app/assets/image/',
line_comments: true,
sourcemap: true
}))
.pipe(gulp.dest('./app/assets/style/'));
I had trouble generating the line number comments using gulp-compass also. I tried a lot of things including matching all the plugin versions to the sample code I used to even completely discarding my code and use the full sample instead to no avail.
On top of its lack of compliance with gulp standards as #ddprrt suggested, gulp-compass seems to be broken now. Besides generating a stylesheet on the destination folder, it also generates another under the {app_root}/css folder. I suspect, the latter is some sort of caching, but that functionality is currently broken. As can be seen here, if you delete that stylesheet and re-run the task, the line number comments will finally show up. Below, I automated this by installing and using the gulp-clean-dest plugin. I have no tried using other plugins, but this hack handles the issue.
var gulp = require("gulp")
, compass = require("gulp-compass")
, cleanDest = require("gulp-clean-dest")
;
gulp.task("compass", function() {
gulp.src("components/sass/style.scss")
.pipe(compass(
{ "sass": "components/sass"
, "image": "builds/development/images"
, "style": "expanded"
, "comments": true
})
.on("error", gutil.log)
)
.pipe(gulp.dest("builds/development/css"))
.pipe(cleanDest("css"))
});

Resources