Supplies a set of functions to Sass that keep physical asset location details out of your source code. Also allows one to define a cache-busting policy or specify asset hosts by url.
This module supplies functions to a Sass compiler which can be called from your Sass code.
For example, the image-url
used here in place of url
adds build-time configuration to resolve the file to the proper location as seen from the web:
.some-selector {
background-image: image-url('cat.jpg');
}
NB Please note that the functions
option of dart-sass/node-sass is still experimental (>= v3.0.0).
This module provides some of the asset functions that came with Compass. Originally a fork of node-sass-asset-functions that was never merged.
image-url($filename: null, $only_path: false)
image-width($filename: null)
image-height($filename: null)
font-url($filename: null, $only-path: false)
font-files($filenames...)
inline-image($filename: null, $mime-type: null)
lookup($keys...)
Basic usage is as easy as setting the functions
property:
// non-module, require usage
const sass = require('sass');
const { default: assetFunctions } = require('@localnerve/sass-asset-functions');
const result = sass.compile(scss_filename, {
functions: assetFunctions(/* options */)
[, options...]
});
// module usage
import sass from 'sass';
import assetFunctions from '@localnerve/sass-asset-functions';
const result = sass.compile(scss_filename, {
functions: assetFunctions(/* options */)
[, options...]
});
All options are optional.
name | type | description |
---|---|---|
sass |
Object | A reference to an alternate Sass compiler to use other than dart-sass (must expose types ). Defaults to undefined and a dart-sass reference is used |
legacyAPI |
Boolean | truthy to use the legacy sass API via the sass render function. Defaults to false |
async |
Boolean | truthy to use modern sass API via the compileAsync function. Required if supplied asset_cache_buster or asset_host function options are asynchronous. Defaults to false |
images_path |
String | The build-time file path to images. Defaults to public/images |
fonts_path |
String | The build-time file path to fonts. Defaults to public/fonts |
http_images_path |
String | The path to images as seen from the web (nothing to do with http). Defaults to /images |
http_fonts_path |
String | The path to images as seen from the web (nothing to do with http). Defaults to /fonts |
asset_cache_buster |
Function | Signature (http_path, real_path, callback(new_url)). Supply to perform url transform for image-url or font-url , presumably for asset cache busting, but useful for any change to the url path (before fragment) |
asset_host |
Function | Signature (http_path, callback(new_url)). Supply to perform url transform for image-url or font-url , presumably to define an asset host, but useful for any change to the url before the path |
data |
Object | An object of arbitrary data to reference at build-time. Defaults to (empty) |
You can specify the paths to your resources using the following options (shown with defaults):
{
images_path: 'public/images', // local directory
fonts_path: 'public/fonts',
http_images_path: '/images', // web path
http_fonts_path: '/fonts',
data: {}
}
So if your project images reside in public/img
at build-time instead of public/images
, you use it as follows:
const sass = require('sass');
const { default: assetFunctions } = require('@localnerve/sass-asset-functions');
const result = sass.compile(scss_filename, {
functions: assetFunctions({
images_path: 'public/img',
http_images_path: '/images'
})
[, options...]
});
Example using the node-sass compiler using the new option sass
.
const sass = require('node-sass');
const { default: assetFunctions } = require('@localnerve/sass-asset-functions');
const result = sass.compile(scss_filename, {
functions: assetFunctions({ sass })
[, options...]
});
This function retrieves arbitrary build-time data for reference in stylesheet compilation. Could be an asset name, prefix, or could be a whole list or map of things. Here's the list of javascript type mappings (everything else returns SassNull):
- Boolean => SassBoolean
- Number => SassNumber
- String => SassString
- Array => SassList
- Set => SassList
- Object => SassMap
- Map => SassMap
const result = sass.compile(scss_filename, {
functions: assetFunctions({
data: {
'hero-image-names': {
big: 'hero-1920x300.webp',
medium: 'hero-1440x300.webp',
small: 'hero-1024x300.webp'
},
nested: {
process: true,
'process-map': {
one: 'one',
two: 'two'
}
}
}
})
});
$hero-images: lookup('hero-image-names');
@each $key, $val in $hero-images {
.hero-image-#{$key} {
background-image: image-url($val);
}
}
$nested-process: lookup('nested', 'process');
$nested-data: lookup('nested', 'process-map');
@if $nested-process {
@each $key, $val in $nested-data {
.process-#{$key} {
content: '#{$val}';
}
}
}
const result = sass.compile(scss_filename, {
functions: assetFunctions({
asset_host: (http_path, done) => {
done('http://assets.example.com');
// or use the supplied path to calculate a host
done(`http://assets${http_path.length % 4}.example.com`);
}
})
[, options...]
});
When this function returns a string, it's set as the query of the path. When returned an object, path
and query
will be used.
const result = sass.compile(scss_filename, {
functions: assetFunctions({
asset_cache_buster: (http_path, real_path, done) => {
done('v=123');
}
})
[, options...]
});
Here we include the file's hexdigest in the path, using the hexdigest
module.
For example, /images/myimage.png
would become /images/myimage-8557f1c9b01dd6fd138ba203e6a953df6a222af3.png
.
const sass = require('sass');
const path = require('path');
const fs = require('fs');
const hexdigest = require('hexdigest');
const { default: assetFunctions } = require('@localnerve/sass-asset-functions');
const result = sass.compileAsync(scss_filename, {
functions: assetFunctions({
async: true,
asset_cache_buster: (http_path, real_path, done) => {
hexdigest(real_path, 'sha1', (err, digest) => {
if (err) {
// an error occurred, maybe the file doesn't exist.
// Calling `done` without arguments will result in an unmodified path.
done();
} else {
const extname = path.extname(http_path);
const basename = path.basename(http_path, extname);
const new_name = `${basename}-${digest}${extname}`;
done({path: path.join(path.dirname(http_path), new_name), query: null});
}
});
}
})
[, options...]
});
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request