Sass Plugin for Theme Tools
Theme core plugins let you easily pass in configuration and get a set of Gulp-ready task functions back that have sensible defaults and work well together.
Features
- Scss compiling via
gulp-sass
& libsass - Sourcemaps
- Handy PostCSS plugins:
- Autoprefixer
- URL to inline or copy assets
- Discard Duplicates to remove duplicated rules
- Flexbox bug fixes
-
CSS Nano for minification if
NODE_ENV=production
- Documentation generation via SassDoc
- Linting via Stylelint
- Native OS Notifications for Errors
- Better Sass @import Globbing that allows nested globbed imports
Getting Started
Requirements
- Gulp 4 installed with
npm install --save gulp@4
Install
npm install @theme-tools/plugin-sass --save
Configure
The config that is passed in is merged with config.default.js
. We suggest starting with config.simple.js
to get started:
cp node_modules/@theme-tools/plugin-sass/config.simple.js config.sass.js
See details on configuration below.
Basic Setup
Add this to your gulpfile.js
:
const gulp = require('gulp');
const config = {};
config.sass = require('./config.sass.js');
const sassTasks = require('@theme-tools/plugin-sass')(config.sass);
gulp.task('sass', sassTasks.compile);
gulp.task('watch:sass', sassTasks.watch);
gulp.task('validate:sass', sassTasks.validate);
gulp.task('clean:sass', sassTasks.clean);
gulp.task('docs:sass', sassTasks.docs);
- See Task Details below
- See Setting up SassDoc below
- See Setting up Stylelint below
Details
Tasks
These tasks are methods inside sassTasks
from the above code example. You can run them anyway you can run a function, though they are often ran via Gulp. All tasks take a callback function as the first and only parameter that will run when the task is done - exactly how gulp.task()
, gulp.parallel()
, and gulp.series()
want.
sassTasks.compile()
- Compile Sass
The main task that takes Sass files and turns them into CSS files after passing them through AutoPrefixer.
sassTasks.validate()
- Validate Sass using Stylelint
If you have a Stylelint config present next to your Gulpfile, then this will run that for you. Disabled by default.
sassTasks.clean()
- Clean compiled CSS.
Deletes files that are made by the other tasks.
sassTasks.docs()
- Create documentation using SassDoc
Creates SassDoc documentation for you.
sassTasks.watch()
- Watch Sass
The watch task that will fire off the compile, validate, and docs tasks (if enabled).
Configuration
All configuration is deep merged with config.default.js
.
src
Type: Array<String>
Default: [ 'scss/**/*.scss' ]
The collection of files to compile, watch, validate, and document. This is passed to gulp.src
. Supports globbing.
dest
Type: String
Default: 'dest/'
Where to output the compiled files: CSS files, SourceMaps, and SassDoc output ends up here.
extraWatches
Type: Array<String>
Default: []
Extra collection of files to watch; when these change the enabled tasks (compile, validate, docs) will run (but not with these added to their src
). Supports globbing.
flattenDestOutput
Type: Boolean
Default: true
If true
, no folders will be made in the dest
folder, and all files will be one level deep. If false
, then the folders will be made; so for example:
- This
scss/path/to/file.scss
- Compiles to
dest/path/to/file.css
sourceComments
Type: Boolean
Default: false
Enables additional debugging information in the output file as CSS comments. Shouldn't need to use unless SourceMaps isn't working for you. Passed to node-sass
's sourceComments
.
sourceMapEmbed
Type: Boolean
Default: false
Embed SourceMaps in CSS file or in own .css.map
file? Passed to node-sass
's sourceMapEmbed
.
outputStyle
Type: String
Default: 'expanded'
Values: nested
, expanded
, compact
, compressed
Determines the output format of the final CSS style. Passed to node-sass
's outputStyle
.
autoPrefixerBrowsers
Type: Array<String>
Default: [ 'last 2 versions', 'IE >= 10' ]
Values: see list.
Based on the browsers you want to support, this adds the vendor prefixes you'll need. It's recommended to have Stylelint check to make sure you don't write vendor prefixes in your source code as well.
includePaths
Type: Array<String>
Default: [ './node_modules' ]
An array of paths that LibSass can look in to attempt to resolve your @import
declarations. Useful for importing libraries you install via npm. Passed to node-sass
's includePaths
.
lint
Type: Object
Config for Stylelint; see below for properties.
lint.enabled
Type: Boolean
Default: false
Uses Stylelint. If enabled, this will export out a sassTasks.validate
task, and lint the most recently changed file on watch triggers. Requires Stylelint configuration to be set up.
lint.onWatch
Type: Boolean
Default: true
If true
, lint the files that just changed after each save. If false
, then it is not ran on watch, but you still have the full lint task of sassTasks.validate()
.
sassdoc
Type: Object
Configuration for SassDoc; see below for properties.
sassdoc.enabled
Type: Boolean
Default: false
If enabled, you'll have a sassTasks.docs()
task and it'll trigger on watch.
sassdoc.dest
Type: String
Default: 'dest/sassdoc'
Where to compile SassDoc to.
sassdoc.verbose
Type: Boolean
Default: false
Show more debugging information.
sassdoc.basePath
Type: String
Default: ''
Allows you to have a "View Source" link next to code documentation to it's GitHub/Bitbucket view. Set it to https://github.com/USERNAME/REPOSITORY/tree/master
(or /blob/<branch_name>
). Passed to SassDoc's basePath
.
sassdoc.exclude
Type: Array<String>
Default: []
Doesn't document these files. Passed to SassDoc's exclude
.
sassdoc.theme
Type: String
Default: 'default'
Theme for SassDoc. Passed to SassDoc's theme
.
sassdoc.sort
Type: Array<String>
Default: [ 'file', 'group', 'line>' ]
Passed to SassDoc's sort
.
urlAssets
Type: Object
Uses postcss-url
to take assets found in the url()
s of the sass and will inline or copy them to the destination directory (dest
option) and rewrite what's found in the url()
.
urlAssets.enabled
Type: Boolean
Default: false
Turn this behavior on or off.
urlAssets.basePath
Type: Array<String>
Default: []
Path or array of absolute paths to search for assets. Passes to the basePath
option.
urlAssets.maxInlineSize
Type: Number
Default: 14
Max filesize, in kilobytes, to inline via Base64. If bigger, it copies the file. Passes to maxSize
option
urlAssets.filter
Type: Regex
, String
, or Function
Default: All files
A regular expression e.g. /\.svg$/
, a minimatch string e.g. '**/*.svg'
or a custom filter function to determine whether a file should be inlined. Example: url => !url.pathname.startsWith('icons')
.
urlAssets.destSubDir
Type: String
Default: ''
If used, assets are placed in this directory inside the dest
directory where CSS is compiled to.
exportData
Type: Object
Uses @theme-tools/sass-export-data
to export Sass Maps and other vars as JSON. All options in this variable are passed directly to that module, please see it for docs & details.
exportData.enabled
Type: Boolean
Default: false
functions
Type: Object
Default: {}
Add your own custom Sass functions by passing in an object of functions according to those docs.
importers
Type: Array
Default: []
Add your own custom Sass importer by passing in an array of functions according to those docs.
Setup Details
Setting up Stylelint
This uses Stylelint via gulp-stylelint
- see those pages for further docs.
- Set
lint.enabled
totrue
. - Run
npm install --save-dev stylelint-scss
- Create these files:
.stylelintignore
(for ignored files) and a config file,.stylelintrc.js
with this:
// Docs: http://stylelint.io
// Style lint rule detail: https://github.com/stylelint/stylelint/tree/master/src/rules/RULE-NAME
module.exports = {
plugins: [
"stylelint-scss"
],
rules: {
// Just some sample rules to get you started.
"declaration-no-important": true,
"indentation": 2,
"max-nesting-depth": 3,
"selector-max-specificity": "0,3,3",
"selector-no-id": true,
"scss/at-extend-no-missing-placeholder": true,
"at-rule-no-vendor-prefix": true,
"media-feature-name-no-vendor-prefix": true,
"property-no-vendor-prefix": true,
"selector-no-vendor-prefix": true,
"value-no-vendor-prefix": true
}
};
You can disable rules for a single place using this, or other, approaches:
.utility--spacing-down {
margin-bottom: $spacing !important; // stylelint-disable-line declaration-no-important
}
Sometimes !important
is ok; most of the time it's not.
Setting up SassDoc
- Set
sassdoc.enabled
totrue
- Use SassDoc comment annotations in your Sass. These all use comments like
///
instead of the regular//
. See below for examples. - Open
sassdoc.dest
(defaults todest/sassdoc/
) to view SassDoc.
/// Link Color
$color--link: blue;
/// Center an element vertically and/or horizontally in its container.
/// @param $horizontally [true] - center horizontally
/// @param $vertically [true] - center vertically
@mixin center($horizontally: true, $vertically: true) {
position: relative;
@if ($horizontally == true and $vertically == true) {
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
@if ($vertically == true and $horizontally == false) {
top: 50%;
transform: translateY(-50%);
}
@if ($horizontally == true and $vertically == false) {
left: 50%;
transform: translateX(-50%);
}
}
Theme Core Events
This is only info for other Theme Core plugin developers.
'reload'
emit This event is emmited when files are done compiling. The first paramater is a String of the files changed.