commit
ee039186f0
21
.editorconfig
Normal file
21
.editorconfig
Normal file
|
@ -0,0 +1,21 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
|
||||
# Change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# We recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
155
.eslintrc
Normal file
155
.eslintrc
Normal file
|
@ -0,0 +1,155 @@
|
|||
env:
|
||||
mocha: true
|
||||
node: true
|
||||
|
||||
# globals:
|
||||
#########################
|
||||
## Only add globals if you're absolutely certain they need to be globals
|
||||
##########################
|
||||
# console: true
|
||||
|
||||
#########################
|
||||
## set to 0 to allow
|
||||
## set to 1 to disallow as warning
|
||||
## set to 2 to disallow as error
|
||||
#########################
|
||||
rules:
|
||||
#########################
|
||||
## Optional Rules
|
||||
#########################
|
||||
# Disallow use of `console`
|
||||
no-console: 2
|
||||
|
||||
# Disallow warning comments
|
||||
no-warning-comments:
|
||||
- 1
|
||||
- terms
|
||||
- todo
|
||||
- fixme
|
||||
location
|
||||
- anywhere
|
||||
|
||||
# Warns when variables are defined but never used
|
||||
no-unused-vars: 1
|
||||
|
||||
# Enforces comma style (first or last)
|
||||
comma-style:
|
||||
- 2
|
||||
- last
|
||||
|
||||
# Enforces one true `this` variable
|
||||
consistent-this:
|
||||
- 2
|
||||
- self
|
||||
# Allows dangling underscores in identifiers
|
||||
no-underscore-dangle: 2
|
||||
|
||||
# Enforces function expressions to have a name
|
||||
func-names: 0
|
||||
|
||||
# Set maximum depth of nested callbacks
|
||||
max-nested-callbacks:
|
||||
- 1
|
||||
- 3
|
||||
|
||||
#########################
|
||||
## Core Rules
|
||||
##########################
|
||||
# Enforces camel case names
|
||||
camelcase: 2
|
||||
|
||||
# Prohibit use of == and != in favor of === and !==
|
||||
eqeqeq: 2
|
||||
|
||||
# Suppresses warnings about == null comparisons
|
||||
no-eq-null: 2
|
||||
|
||||
# No mixing tabs and spaces, with 2 spaces only
|
||||
no-mixed-spaces-and-tabs: 2
|
||||
|
||||
# Prohibits use of a variable before it is defined
|
||||
no-use-before-define: 2
|
||||
|
||||
# Requires capitalized names for constructor functions
|
||||
new-cap: 2
|
||||
|
||||
# Prohibits use of explicitly undeclared variables
|
||||
no-undef: 2
|
||||
|
||||
# Enforces Use Strict at the top of function scope
|
||||
strict:
|
||||
- 2
|
||||
- global
|
||||
|
||||
# Requires variable declarations to be at the top
|
||||
vars-on-top: 2
|
||||
|
||||
# Enforce curly braces around blocks in loops and conditionals
|
||||
curly: 2
|
||||
|
||||
# Prohibits the use of immediate function invocations w/o wrapping in parentheses
|
||||
wrap-iife: 2
|
||||
|
||||
# Prohibits `argument.caller` and `argument.callee`
|
||||
no-caller: 2
|
||||
|
||||
# Requires all `for in` loops to filter object's items
|
||||
guard-for-in: 2
|
||||
|
||||
# Prohibits comparing a variable against itself
|
||||
no-self-compare: 2
|
||||
|
||||
# Prohibits use of `undefined` variable
|
||||
no-undefined: 0
|
||||
|
||||
# Prohibits nested ternaries
|
||||
no-nested-ternary: 2
|
||||
|
||||
# Enforces a space before blocks
|
||||
space-before-blocks:
|
||||
- 2
|
||||
- always
|
||||
|
||||
# Enforces spaces following keywords
|
||||
space-after-keywords:
|
||||
- 2
|
||||
- always
|
||||
- checkFunctionKeyword: true
|
||||
|
||||
# Enforces quoted property names
|
||||
quote-props:
|
||||
- 2
|
||||
- always
|
||||
|
||||
# Enforces padded blocks
|
||||
padded-blocks:
|
||||
- 1
|
||||
- never
|
||||
|
||||
# Enforce functions as expressions
|
||||
func-style:
|
||||
- 2
|
||||
- expression
|
||||
|
||||
# Require brace style
|
||||
brace-style:
|
||||
- 2
|
||||
- stroustrup
|
||||
|
||||
# Prohibits Yoda conditions
|
||||
yoda:
|
||||
- 2
|
||||
- never
|
||||
|
||||
# Enforce use of single quotation marks for strings.
|
||||
quotes:
|
||||
- 2
|
||||
- single
|
||||
|
||||
# Enforces space inside of brackets (except property name)
|
||||
space-in-brackets:
|
||||
- 2
|
||||
- always
|
||||
- propertyName: false
|
||||
singleValue: false
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
- node
|
||||
- iojs
|
||||
|
|
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,3 +1,18 @@
|
|||
# Gulp Sass Changelog
|
||||
|
||||
## v2.0.0-alpha.1
|
||||
**March 26, 2015**
|
||||
|
||||
* **New** Added `renderSync` option that can be used through `sass.sync()`
|
||||
|
||||
### March 24, 2015
|
||||
* **Change** Updated to `node-sass` 3.0.0-alpha.1
|
||||
* **New** Added support for `gulp-sourcemaps` including tests
|
||||
* **New** Added `.editorconfig` for development consistency
|
||||
* **New** Added linting and test for said linting
|
||||
* **Change** Updated the README
|
||||
* **New** `logError` function to make streaming errors possible instead of breaking the stream
|
||||
|
||||
### 1.3.3
|
||||
|
||||
* updated to node-sass 2.0 (final)
|
||||
|
|
63
CONTRIBUTING.md
Normal file
63
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Contributing to Gulp Sass
|
||||
|
||||
Gulp Sass is a very light-weight [Gulp](https://github.com/gulpjs/gulp) wrapper for [`node-sass`](https://github.com/sass/node-sass), which in turn is a Node binding for [`libsass`](https://github.com/sass/libsass), which in turn is a port of [`Sass`](https://github.com/sass/sass).
|
||||
|
||||
## Submitting Issues
|
||||
|
||||
* Before creating a new issue, perform a [cursory search](https://github.com/issues?utf8=%E2%9C%93&q=repo%3Adlmanning%2Fgulp-sass+repo%3Asass%2Fnode-sass+repo%3Asass%2Flibsass+repo%3Asass%2Fsass+repo%3Asass-eyeglass%2Feyeglass) in the Gulp Sass, Node Sass, Libsass, and main Sass repos to see if a similar issue has already been submitted.
|
||||
* You can create an issue [here](https://github.com/dlmanning/gulp-sass/issues). Please include as many details as possible in your report.
|
||||
* Issue titles should be descriptive, explaining at the high level what it is about.
|
||||
* Please include the version of `gulp-sass` you are using.
|
||||
* Do not open a [pull request](#pull-requests) to resolve an issue without first receiving feedback from a `collaborator` or `owner` and having them agree on a solution forward.
|
||||
* Include screenshots and animated GIFs whenever possible; they are immensely helpful.
|
||||
* Issues that have a number of sub-items that need to be complete should use [task lists](https://github.com/blog/1375%0A-task-lists-in-gfm-issues-pulls-comments) to track the sub-items in the main issue comment.
|
||||
|
||||
|
||||
## Pull Requests
|
||||
|
||||
* **DO NOT ISSUE A PULL REQUEST WITHOUT FIRST [SUBMITTING AN ISSUE](#submitting-issues)**
|
||||
* Pull requests should reference their related issues. If the pull request closes an issue, [please reference its closing in your commit messages](https://help.github.com/articles/closing-issues-via-commit-messages/). Pull requests not referencing any issues will be closed.
|
||||
* Pull request titles should be descriptive, explaining at the high level what it is doing, and should be written in the same style as [Git commit messages](#git-commit-messages).
|
||||
* Update the `CHANGELOG` with the changes made by your pull request, making sure to use the proper [Emoji](#emoji-cheatsheet).
|
||||
* Follow our JavaScript styleguides. Tests will fail if you do not.
|
||||
* Ensure that you have [EditorConfig](http://editorconfig.org/) installed in your editor of choice and that it is functioning properly.
|
||||
* Do not squash or rebase your commits when submitting a Pull Request. It makes it much harder to follow your work and make incremental changes.
|
||||
* Update the [CHANGELOG](#maintaining-thechangelog) with your changes.
|
||||
* Branches should be made off of the most current `master` branch from `git@github.com:dlmanning/gulp-sass.git`
|
||||
* Pull requests should be made into our [master](https://github.com/dlmanning/gulp-sass/tree/master) branch.
|
||||
|
||||
### Git Commit Messages
|
||||
|
||||
* Use the present tense (`"Add feature"` not `"Added Feature"`)
|
||||
* Use the imperative mood (`"Move cursor to…"` not `"Moves cursor to…"`)
|
||||
* Limit the first line to 72 characters or less
|
||||
* Consider including relevant Emoji from our [Emoji cheatsheet](#emoji-cheatsheet)
|
||||
|
||||
## Creating a New Version
|
||||
|
||||
Versioning is done through [SEMVER](http://semver.org/). When creating a new version, create new release branch off of `master` with the version's name, and create a new tag with `v` prefixed with the version's name from that branch.
|
||||
|
||||
For instance, if you are creating version `1.1.0`, you would create a branch `release/1.1.0` from `master` and create a tag `v1.1.0` from branch `release/1.1.0`.
|
||||
|
||||
### Maintaining the Changelog
|
||||
|
||||
The Changelog should have a list of changes made for each version. They should be organized so additions come first, changes come second, and deletions come third. Version numbers should be 2nd level headers with the `v` in front (like a tag) and the date of the version's most recent update should be underneath in italics.
|
||||
|
||||
Changelog messages do not need to cover each individual commit made, but rather should have individual summaries of the changes made. Changelog messages should be written in the same style as [Git commit messages](#git-commit-messages).
|
||||
|
||||
## Emoji Cheatsheet
|
||||
|
||||
When creating creating commits or updating the CHANGELOG, please **start** the commit message or update with one of the following applicable Emoji. Emoji should not be used at the start of issue or pull request titles.
|
||||
|
||||
* :art: `:art:` when improving the format/structure of the code
|
||||
* :racehorse: `:racehorse:` when improving performance
|
||||
* :memo: `:memo:` when writing long-form text (documentation, guidelines, principles, etc…)
|
||||
* :bug: `:bug:` when fixing a bug
|
||||
* :fire: `:fire:` when removing code or files
|
||||
* :green_heart: `:green_heart:` when fixing the CI build
|
||||
* :white_check_mark: `:white_check_mark:` when adding tests
|
||||
* :lock: `:lock:` when dealing with security
|
||||
* :arrow_up: `:arrow_up:` when upgrading dependencies
|
||||
* :arrow_down: `:arrow_down:` when downgrading dependencies
|
||||
* :shirt: `:shirt:` when removing linter warnings
|
||||
* :shipit: `:shipit:` when creating a new release
|
89
README.md
89
README.md
|
@ -1,21 +1,16 @@
|
|||
[![Build Status](https://travis-ci.org/dlmanning/gulp-sass.svg?branch=master)](https://travis-ci.org/dlmanning/gulp-sass)
|
||||
# gulp-sass [![Build Status](https://travis-ci.org/dlmanning/gulp-sass.svg?branch=master)](https://travis-ci.org/dlmanning/gulp-sass) [![Join the chat at https://gitter.im/dlmanning/gulp-sass](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dlmanning/gulp-sass?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
gulp-sass
|
||||
=========
|
||||
|
||||
[![Join the chat at https://gitter.im/dlmanning/gulp-sass](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dlmanning/gulp-sass?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Sass plugin for [gulp](https://github.com/gulpjs/gulp).
|
||||
Sass plugin for [Gulp](https://github.com/gulpjs/gulp).
|
||||
|
||||
# Install
|
||||
|
||||
```
|
||||
npm install gulp-sass
|
||||
npm install gulp-sass --save-dev
|
||||
```
|
||||
|
||||
# Basic Usage
|
||||
|
||||
Something like this:
|
||||
Something like this will compile your Sass files:
|
||||
|
||||
```javascript
|
||||
var gulp = require('gulp');
|
||||
|
@ -23,36 +18,31 @@ var sass = require('gulp-sass');
|
|||
|
||||
gulp.task('sass', function () {
|
||||
gulp.src('./scss/*.scss')
|
||||
.pipe(sass())
|
||||
.pipe(sass().on('error', sass.logError))
|
||||
.pipe(gulp.dest('./css'));
|
||||
});
|
||||
```
|
||||
|
||||
Options passed as a hash into `sass()` will be passed along to [`node-sass`](https://github.com/sass/node-sass).
|
||||
You can also compile synchronously, doing something like this:
|
||||
|
||||
If you want to use the indented syntax (`.sass`) as the top level file, use `sass({indentedSyntax: true})`.
|
||||
```javascript
|
||||
var gulp = require('gulp');
|
||||
var sass = require('gulp-sass');
|
||||
|
||||
## gulp-sass specific options
|
||||
gulp.task('sass', function () {
|
||||
gulp.src('./scss/*.scss')
|
||||
.pipe(sass.sync().on('error', sass.logError))
|
||||
.pipe(gulp.dest('./css'));
|
||||
});
|
||||
```
|
||||
|
||||
#### `errLogToConsole: true`
|
||||
## Options
|
||||
|
||||
If you pass `errLogToConsole: true` into the options hash, sass errors will be logged to the console instead of generating a `gutil.PluginError` object. Use this option with `gulp.watch` to keep gulp from stopping every time you mess up your sass.
|
||||
|
||||
#### `onSuccess: callback`
|
||||
|
||||
Pass in your own callback to be called upon successful compilation by node-sass. The callback has the form `callback(css)`, and is passed the compiled css as a string. Note: This *does not* prevent gulp-sass's default behavior of writing the output css file.
|
||||
|
||||
#### `onError: callback`
|
||||
|
||||
Pass in your own callback to be called upon a sass error from node-sass. The callback has the form `callback(err)`, where err is the error string generated by libsass. Note: this *does* prevent an actual `gulpPluginError` object from being created.
|
||||
|
||||
#### `sync: true`
|
||||
|
||||
If you pass `sync: true` into the options hash, sass.renderSync will be called, instead of sass.render. This should help when memory and/or cpu usage is getting very high when rendering many and/or big files.
|
||||
Pass in options just like you would for [`node-sass`](https://github.com/sass/node-sass#options); they will be passed along just as if you were using `node-sass`.
|
||||
|
||||
## Source Maps
|
||||
|
||||
gulp-sass can be used in tandem with [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) to generate source maps for the SASS to CSS compilation. You will need to initialize [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) prior to running the gulp-sass compiler and write the source maps after.
|
||||
`gulp-sass` can be used in tandem with [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) to generate source maps for the Sass to CSS compilation. You will need to initialize [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) prior to running `gulp-sass` and write the source maps after.
|
||||
|
||||
```javascript
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
|
@ -62,11 +52,9 @@ gulp.src('./scss/*.scss')
|
|||
.pipe(sass())
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('./css'));
|
||||
|
||||
// will write the source maps inline in the compiled CSS files
|
||||
```
|
||||
|
||||
By default, [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) writes the source maps inline in the compiled CSS files. To write them to a separate file, specify a relative file path in the `sourcemaps.write()` function.
|
||||
By default, [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) writes the source maps inline in the compiled CSS files. To write them to a separate file, specify a path relative to the `gulp.dest()` destination in the `sourcemaps.write()` function.
|
||||
|
||||
```javascript
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
|
@ -76,39 +64,14 @@ gulp.src('./scss/*.scss')
|
|||
.pipe(sass())
|
||||
.pipe(sourcemaps.write('./maps'))
|
||||
.pipe(gulp.dest('./css'));
|
||||
|
||||
// will write the source maps to ./dest/css/maps
|
||||
```
|
||||
|
||||
# Imports and Partials
|
||||
|
||||
gulp-sass now automatically passes along the directory of every scss file it parses as an include path for node-sass. This means that as long as you specify your includes relative to path of your scss file, everything will just work.
|
||||
|
||||
scss/includes/_settings.scss:
|
||||
|
||||
```scss
|
||||
$blue: #3bbfce;
|
||||
$margin: 16px;
|
||||
```
|
||||
|
||||
scss/style.scss:
|
||||
|
||||
```scss
|
||||
@import "includes/settings";
|
||||
|
||||
.content-navigation {
|
||||
border-color: $blue;
|
||||
color:
|
||||
darken($blue, 9%);
|
||||
}
|
||||
|
||||
.border {
|
||||
padding: $margin / 2;
|
||||
margin: $margin / 2;
|
||||
border-color: $blue;
|
||||
}
|
||||
```
|
||||
|
||||
# Issues
|
||||
|
||||
Before submitting an issue, please understand that gulp-sass is only a wrapper for [node-sass](https://github.com/sass/node-sass), which in turn is a node front end for [libsass](https://github.com/sass/libsass). Missing sass features and errors should not be reported here.
|
||||
`gulp-sass` is a very light-weight wrapper around [`node-sass`](https://github.com/sass/node-sass), which in turn is a Node binding for [`libsass`](https://github.com/sass/libsass), which in turn is a port of [`Sass`](https://github.com/sass/sass). Because of this, the issue you're having likely isn't a `gulp-sass` issue, but an issue with one of those three projects.
|
||||
|
||||
If you have a feature request/question how Sass works/concerns on how your Sass gets compiled/errors in your compiling, it's likely a `libsass` or `Sass` issue and you should file your issue with one of those projects.
|
||||
|
||||
If you're having problems with the options you're passing in, it's likely a `node-sass` or `libsass` issued and you should file your issue with one of those projects.
|
||||
|
||||
We may, in the course of resolving issues, direct you to one of these other projects. If we do so, please follow up by searching that project's issue queue (both open and closed) for your problem and, if it doesn't exist, filing an issue with them.
|
||||
|
|
206
index.js
206
index.js
|
@ -1,104 +1,156 @@
|
|||
var fs = require('fs')
|
||||
, map = require('map-stream')
|
||||
, nodeSass = require('node-sass')
|
||||
, path = require('path')
|
||||
, gutil = require('gulp-util')
|
||||
, clone = require('clone')
|
||||
, ext = gutil.replaceExtension
|
||||
, applySourceMap = require('vinyl-sourcemaps-apply')
|
||||
;
|
||||
'use strict';
|
||||
|
||||
module.exports = function (options) {
|
||||
var gutil = require('gulp-util');
|
||||
var through = require('through2');
|
||||
var assign = require('object-assign');
|
||||
var path = require('path');
|
||||
var applySourceMap = require('vinyl-sourcemaps-apply');
|
||||
|
||||
function sass (file, cb) {
|
||||
var opts = options ? clone(options) : {};
|
||||
var fileDir = path.dirname(file.path);
|
||||
var PLUGIN_NAME = 'gulp-sass';
|
||||
|
||||
//////////////////////////////
|
||||
// Main Gulp Sass function
|
||||
//////////////////////////////
|
||||
var gulpSass = function gulpSass(options, sync) {
|
||||
return through.obj(function(file, enc, cb) {
|
||||
var opts,
|
||||
filePush,
|
||||
errorM,
|
||||
callback,
|
||||
result;
|
||||
|
||||
if (file.isNull()) {
|
||||
return cb(null, file);
|
||||
}
|
||||
if (file.isStream()) {
|
||||
return cb(new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
|
||||
}
|
||||
if (path.basename(file.path).indexOf('_') === 0) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
opts = assign({}, options);
|
||||
opts.data = file.contents.toString();
|
||||
|
||||
// Ensure `indentedSyntax` is true if a `.sass` file
|
||||
if (path.extname(file.path) === '.sass') {
|
||||
opts.indentedSyntax = true;
|
||||
}
|
||||
|
||||
// Ensure file's parent directory in the include path
|
||||
if (opts.includePaths) {
|
||||
if (typeof opts.includePaths === 'string') {
|
||||
opts.includePaths = [opts.includePaths];
|
||||
}
|
||||
}
|
||||
else {
|
||||
opts.includePaths = [];
|
||||
}
|
||||
|
||||
opts.includePaths.push(path.dirname(file.path));
|
||||
|
||||
// Generate Source Maps if plugin source-map present
|
||||
if (file.sourceMap) {
|
||||
opts.sourceMap = file.path;
|
||||
opts.omitSourceMapUrl = true;
|
||||
}
|
||||
|
||||
opts.data = file.contents.toString();
|
||||
opts.file = file.path;
|
||||
//////////////////////////////
|
||||
// Handles returning the file to the stream
|
||||
//////////////////////////////
|
||||
filePush = function filePush(sassObj) {
|
||||
var sassMap,
|
||||
sassMapFile,
|
||||
sassFileSrc;
|
||||
|
||||
if (opts.includePaths && Array.isArray(opts.includePaths)) {
|
||||
if (opts.includePaths.indexOf(fileDir) === -1) {
|
||||
opts.includePaths.push(fileDir);
|
||||
// Build Source Maps!
|
||||
if (sassObj.map) {
|
||||
// Transform map into JSON
|
||||
sassMap = JSON.parse(sassObj.map.toString());
|
||||
// Grab the stdout and transform it into stdin
|
||||
sassMapFile = sassMap.file.replace('stdout', 'stdin');
|
||||
// Grab the base file name that's being worked on
|
||||
sassFileSrc = file.path.split('/').pop();
|
||||
// Replace the stdin with the original file name
|
||||
sassMap.sources[sassMap.sources.indexOf(sassMapFile)] = sassFileSrc;
|
||||
// Replace the map file with the original file name
|
||||
sassMap.file = sassFileSrc;
|
||||
// Apply the map
|
||||
applySourceMap(file, sassMap);
|
||||
}
|
||||
} else {
|
||||
opts.includePaths = [fileDir];
|
||||
}
|
||||
|
||||
opts.success = function (obj) {
|
||||
if (typeof opts.onSuccess === 'function') opts.onSuccess(obj);
|
||||
file.contents = sassObj.css;
|
||||
file.path = gutil.replaceExtension(file.path, '.css');
|
||||
|
||||
if (obj.map && typeof obj.map === 'string') {
|
||||
// hack to remove the already added sourceMappingURL from libsass
|
||||
obj.css = obj.css.replace(/\/\*#\s*sourceMappingURL\=.*\*\//, '');
|
||||
cb(null, file);
|
||||
};
|
||||
|
||||
// libsass gives us sources' paths relative to file;
|
||||
// gulp-sourcemaps needs sources' paths relative to file.base;
|
||||
// so alter the sources' paths to please gulp-sourcemaps.
|
||||
obj.map = JSON.parse(obj.map);
|
||||
//////////////////////////////
|
||||
// Handles error message
|
||||
//////////////////////////////
|
||||
errorM = function errorM(error) {
|
||||
var relativePath = '',
|
||||
filePath = error.file === 'stdin' ? file.path : error.file,
|
||||
message = '';
|
||||
|
||||
if (obj.map.sources) {
|
||||
obj.map.sources = obj.map.sources.map(function(source) {
|
||||
var abs = path.resolve(path.dirname(file.path), source);
|
||||
return path.relative(file.base, abs);
|
||||
});
|
||||
filePath = filePath ? filePath : file.path;
|
||||
relativePath = path.relative(process.cwd(), filePath);
|
||||
|
||||
obj.map = JSON.stringify(obj.map);
|
||||
applySourceMap(file, obj.map);
|
||||
message += gutil.colors.underline(relativePath) + '\n';
|
||||
message += gutil.colors.gray(' ' + error.line + ':' + error.column) + ' ';
|
||||
message += error.message;
|
||||
|
||||
return cb(new gutil.PluginError(
|
||||
PLUGIN_NAME, message
|
||||
));
|
||||
};
|
||||
|
||||
if (sync !== true) {
|
||||
//////////////////////////////
|
||||
// Async Sass render
|
||||
//////////////////////////////
|
||||
callback = function(error, obj) {
|
||||
if (error) {
|
||||
return errorM(error);
|
||||
}
|
||||
filePush(obj);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
handleOutput(obj, file, cb);
|
||||
};
|
||||
|
||||
opts.error = function (err) {
|
||||
if (opts.errLogToConsole) {
|
||||
gutil.log(gutil.colors.red('[gulp-sass]', err.message, 'on line', err.line + 'in', err.file));
|
||||
return cb();
|
||||
}
|
||||
|
||||
if (typeof opts.onError === 'function') {
|
||||
opts.onError(err);
|
||||
return cb();
|
||||
}
|
||||
|
||||
err.lineNumber = err.line;
|
||||
err.fileName = err.file;
|
||||
|
||||
return cb(new gutil.PluginError('gulp-sass', err));
|
||||
};
|
||||
|
||||
if ( opts.sync ) {
|
||||
try {
|
||||
var output = nodeSass.renderSync(opts);
|
||||
opts.success(output);
|
||||
handleOutput(output, file, cb);
|
||||
} catch(err) {
|
||||
opts.error(err);
|
||||
}
|
||||
} else {
|
||||
nodeSass.render(opts);
|
||||
gulpSass.compiler.render(opts, callback);
|
||||
}
|
||||
else {
|
||||
//////////////////////////////
|
||||
// Sync Sass render
|
||||
//////////////////////////////
|
||||
try {
|
||||
result = gulpSass.compiler.renderSync(opts);
|
||||
|
||||
}
|
||||
|
||||
return map(sass);
|
||||
filePush(result);
|
||||
}
|
||||
catch(error) {
|
||||
return errorM(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function handleOutput(output, file, cb) {
|
||||
file.path = ext(file.path, '.css');
|
||||
file.contents = new Buffer(output.css);
|
||||
cb(null, file);
|
||||
}
|
||||
//////////////////////////////
|
||||
// Sync Sass render
|
||||
//////////////////////////////
|
||||
gulpSass.sync = function sync(options) {
|
||||
return gulpSass(options, true);
|
||||
};
|
||||
|
||||
//////////////////////////////
|
||||
// Log errors nicely
|
||||
//////////////////////////////
|
||||
gulpSass.logError = function logError(error) {
|
||||
gutil.log(gutil.colors.red('[' + PLUGIN_NAME + '] ') + error.message);
|
||||
};
|
||||
|
||||
//////////////////////////////
|
||||
// Store compiler in a prop
|
||||
//////////////////////////////
|
||||
gulpSass.compiler = require('node-sass');
|
||||
|
||||
module.exports = gulpSass;
|
||||
|
|
18
package.json
18
package.json
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"name": "gulp-sass",
|
||||
"version": "1.3.3",
|
||||
"version": "2.0.0",
|
||||
"description": "Gulp plugin for sass",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node test/test.js"
|
||||
"test": "./node_modules/.bin/mocha test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -21,17 +21,15 @@
|
|||
"url": "https://github.com/dlmanning/gulp-sass/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"clone": "~0.1.18",
|
||||
"gulp-util": "^3.0",
|
||||
"map-stream": "~0.1",
|
||||
"node-sass": "^2.0.1",
|
||||
"node-sass": "^3.0.0",
|
||||
"object-assign": "^2.0.0",
|
||||
"through2": "^0.6.3",
|
||||
"vinyl-sourcemaps-apply": "~0.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tape": "~2.3",
|
||||
"concat-stream": "~1.4"
|
||||
},
|
||||
"jshintConfig": {
|
||||
"laxcomma": true
|
||||
"eslint": "^0.17.1",
|
||||
"mocha": "^2.2.1",
|
||||
"should": "^5.2.0"
|
||||
}
|
||||
}
|
||||
|
|
2
test/expected/indent.css
Normal file
2
test/expected/indent.css
Normal file
|
@ -0,0 +1,2 @@
|
|||
body .div {
|
||||
color: blue; }
|
|
@ -1,8 +1,14 @@
|
|||
body {
|
||||
background: pink; }
|
||||
|
||||
footer {
|
||||
background: red; }
|
||||
|
||||
.error, .badError {
|
||||
border: #f00;
|
||||
background: #fdd; }
|
||||
|
||||
.error.intrusion {
|
||||
.error.intrusion, .intrusion.badError {
|
||||
font-size: 1.3em;
|
||||
font-weight: bold; }
|
||||
|
49
test/lint.js
Normal file
49
test/lint.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
'use strict';
|
||||
|
||||
var eslint = require('eslint');
|
||||
var should = require('should');
|
||||
|
||||
var cli = new eslint.CLIEngine();
|
||||
var formatter = cli.getFormatter();
|
||||
|
||||
var report;
|
||||
|
||||
describe('code style guide', function() {
|
||||
it('index.js should follow our lint style guide', function(done) {
|
||||
report = cli.executeOnFiles(['index.js']);
|
||||
if (report.errorCount > 0 || report.warningCount > 0) {
|
||||
console.log(formatter(report.results));
|
||||
}
|
||||
|
||||
should(report.errorCount).equal(0);
|
||||
should(report.warningCount).equal(0);
|
||||
done();
|
||||
});
|
||||
|
||||
it('test/main.js should follow our lint style guide', function(done) {
|
||||
report = cli.executeOnFiles(['test/main.js']);
|
||||
if (report.errorCount > 0 || report.warningCount > 0) {
|
||||
console.log(formatter(report.results));
|
||||
}
|
||||
|
||||
should(report.errorCount).equal(0);
|
||||
should(report.warningCount).equal(0);
|
||||
done();
|
||||
});
|
||||
|
||||
it('test/lint.js should follow our lint style guide', function(done) {
|
||||
cli = new eslint.CLIEngine({
|
||||
'rules': {
|
||||
'no-console': 0
|
||||
}
|
||||
});
|
||||
report = cli.executeOnFiles(['test/lint.js']);
|
||||
if (report.errorCount > 0 || report.warningCount > 0) {
|
||||
console.log(formatter(report.results));
|
||||
}
|
||||
|
||||
should(report.errorCount).equal(0);
|
||||
should(report.warningCount).equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
383
test/main.js
Normal file
383
test/main.js
Normal file
|
@ -0,0 +1,383 @@
|
|||
'use strict';
|
||||
|
||||
var should = require('should');
|
||||
var gutil = require('gulp-util');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var sass = require('../index');
|
||||
|
||||
var createVinyl = function createVinyl(filename, contents) {
|
||||
var base = path.join(__dirname, 'scss');
|
||||
var filePath = path.join(base, filename);
|
||||
|
||||
return new gutil.File({
|
||||
'cwd': __dirname,
|
||||
'base': base,
|
||||
'path': filePath,
|
||||
'contents': contents || fs.readFileSync(filePath)
|
||||
});
|
||||
};
|
||||
|
||||
describe('gulp-sass -- async compile', function() {
|
||||
it('should pass file when it isNull()', function(done) {
|
||||
var stream = sass();
|
||||
var emptyFile = {
|
||||
'isNull': function () {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
stream.on('data', function(data) {
|
||||
data.should.equal(emptyFile);
|
||||
done();
|
||||
});
|
||||
stream.write(emptyFile);
|
||||
});
|
||||
|
||||
it('should emit error when file isStream()', function (done) {
|
||||
var stream = sass();
|
||||
var streamFile = {
|
||||
'isNull': function () {
|
||||
return false;
|
||||
},
|
||||
'isStream': function () {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
stream.on('error', function(err) {
|
||||
err.message.should.equal('Streaming not supported');
|
||||
done();
|
||||
});
|
||||
stream.write(streamFile);
|
||||
});
|
||||
|
||||
it('should compile a single sass file', function(done) {
|
||||
var sassFile = createVinyl('mixins.scss');
|
||||
var stream = sass();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'expected/mixins.css'), 'utf8')
|
||||
);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should compile multiple sass files', function(done) {
|
||||
var files = [
|
||||
createVinyl('mixins.scss'),
|
||||
createVinyl('variables.scss')
|
||||
];
|
||||
var stream = sass();
|
||||
var mustSee = files.length;
|
||||
var expectedPath = 'expected/mixins.css';
|
||||
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
if (cssFile.path.indexOf('variables') !== -1) {
|
||||
expectedPath = 'expected/variables.css';
|
||||
}
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, expectedPath), 'utf8')
|
||||
);
|
||||
mustSee--;
|
||||
if (mustSee <= 0) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
files.forEach(function (file) {
|
||||
stream.write(file);
|
||||
});
|
||||
});
|
||||
|
||||
it('should compile files with partials in another folder', function(done) {
|
||||
var sassFile = createVinyl('inheritance.scss');
|
||||
var stream = sass();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'expected/inheritance.css'), 'utf8')
|
||||
);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should handle sass errors', function(done) {
|
||||
var errorFile = createVinyl('error.scss');
|
||||
var stream = sass();
|
||||
|
||||
stream.on('error', function(err) {
|
||||
err.message.indexOf('property "font" must be followed by a \':\'').should.not.equal(-1);
|
||||
done();
|
||||
});
|
||||
stream.write(errorFile);
|
||||
});
|
||||
|
||||
it('should compile a single sass file if the file name has been changed in the stream', function(done) {
|
||||
var sassFile = createVinyl('mixins.scss');
|
||||
var stream;
|
||||
|
||||
// Transform file name
|
||||
sassFile.path = path.join(path.join(__dirname, 'scss'), 'mixin--changed.scss');
|
||||
|
||||
stream = sass();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
cssFile.path.split('/').pop().should.equal('mixin--changed.css');
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'expected/mixins.css'), 'utf8')
|
||||
);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should preserve changes made in-stream to a Sass file', function(done) {
|
||||
var sassFile = createVinyl('mixins.scss');
|
||||
var stream;
|
||||
|
||||
// Transform file name
|
||||
sassFile.contents = new Buffer('/* Added Dynamically */' + sassFile.contents.toString());
|
||||
|
||||
stream = sass();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
String(cssFile.contents).should.equal('/* Added Dynamically */\n' +
|
||||
fs.readFileSync(path.join(__dirname, 'expected/mixins.css'), 'utf8')
|
||||
);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should work with gulp-sourcemaps', function(done) {
|
||||
var sassFile = createVinyl('inheritance.scss');
|
||||
|
||||
// Expected sources are relative to file.base
|
||||
var expectedSources = [
|
||||
'includes/_cats.scss',
|
||||
'includes/_dogs.sass',
|
||||
'inheritance.scss'
|
||||
];
|
||||
|
||||
var stream;
|
||||
|
||||
sassFile.sourceMap = '{' +
|
||||
'"version": 3,' +
|
||||
'"file": "scss/subdir/multilevelimport.scss",' +
|
||||
'"names": [],' +
|
||||
'"mappings": "",' +
|
||||
'"sources": [ "scss/subdir/multilevelimport.scss" ],' +
|
||||
'"sourcesContent": [ "@import ../inheritance;" ]' +
|
||||
'}';
|
||||
|
||||
stream = sass();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile.sourceMap);
|
||||
cssFile.sourceMap.sources.should.eql(expectedSources);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should compile a single indented sass file', function(done) {
|
||||
var sassFile = createVinyl('indent.sass');
|
||||
var stream = sass();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'expected/indent.css'), 'utf8')
|
||||
);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should parse files in sass and scss', function(done) {
|
||||
var files = [
|
||||
createVinyl('mixins.scss'),
|
||||
createVinyl('indent.sass')
|
||||
];
|
||||
var stream = sass();
|
||||
var mustSee = files.length;
|
||||
var expectedPath = 'expected/mixins.css';
|
||||
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
if (cssFile.path.indexOf('indent') !== -1) {
|
||||
expectedPath = 'expected/indent.css';
|
||||
}
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, expectedPath), 'utf8')
|
||||
);
|
||||
mustSee--;
|
||||
if (mustSee <= 0) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
files.forEach(function (file) {
|
||||
stream.write(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('gulp-sass -- sync compile', function() {
|
||||
it('should pass file when it isNull()', function(done) {
|
||||
var stream = sass.sync();
|
||||
var emptyFile = {
|
||||
'isNull': function () {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
stream.on('data', function(data) {
|
||||
data.should.equal(emptyFile);
|
||||
done();
|
||||
});
|
||||
stream.write(emptyFile);
|
||||
});
|
||||
|
||||
it('should emit error when file isStream()', function (done) {
|
||||
var stream = sass.sync();
|
||||
var streamFile = {
|
||||
'isNull': function () {
|
||||
return false;
|
||||
},
|
||||
'isStream': function () {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
stream.on('error', function(err) {
|
||||
err.message.should.equal('Streaming not supported');
|
||||
done();
|
||||
});
|
||||
stream.write(streamFile);
|
||||
});
|
||||
|
||||
it('should compile a single sass file', function(done) {
|
||||
var sassFile = createVinyl('mixins.scss');
|
||||
var stream = sass.sync();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'expected/mixins.css'), 'utf8')
|
||||
);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should compile multiple sass files', function(done) {
|
||||
var files = [
|
||||
createVinyl('mixins.scss'),
|
||||
createVinyl('variables.scss')
|
||||
];
|
||||
var stream = sass.sync();
|
||||
var mustSee = files.length;
|
||||
var expectedPath = 'expected/mixins.css';
|
||||
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
if (cssFile.path.indexOf('variables') !== -1) {
|
||||
expectedPath = 'expected/variables.css';
|
||||
}
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, expectedPath), 'utf8')
|
||||
);
|
||||
mustSee--;
|
||||
if (mustSee <= 0) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
files.forEach(function (file) {
|
||||
stream.write(file);
|
||||
});
|
||||
});
|
||||
|
||||
it('should compile files with partials in another folder', function(done) {
|
||||
var sassFile = createVinyl('inheritance.scss');
|
||||
var stream = sass.sync();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile);
|
||||
should.exist(cssFile.path);
|
||||
should.exist(cssFile.relative);
|
||||
should.exist(cssFile.contents);
|
||||
String(cssFile.contents).should.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'expected/inheritance.css'), 'utf8')
|
||||
);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
it('should handle sass errors', function(done) {
|
||||
var errorFile = createVinyl('error.scss');
|
||||
var stream = sass.sync();
|
||||
|
||||
stream.on('error', function(err) {
|
||||
err.message.indexOf('property "font" must be followed by a \':\'').should.not.equal(-1);
|
||||
done();
|
||||
});
|
||||
stream.write(errorFile);
|
||||
});
|
||||
|
||||
it('should work with gulp-sourcemaps', function(done) {
|
||||
var sassFile = createVinyl('inheritance.scss');
|
||||
|
||||
// Expected sources are relative to file.base
|
||||
var expectedSources = [
|
||||
'includes/_cats.scss',
|
||||
'includes/_dogs.sass',
|
||||
'inheritance.scss'
|
||||
];
|
||||
|
||||
var stream;
|
||||
|
||||
sassFile.sourceMap = '{' +
|
||||
'"version": 3,' +
|
||||
'"file": "scss/subdir/multilevelimport.scss",' +
|
||||
'"names": [],' +
|
||||
'"mappings": "",' +
|
||||
'"sources": [ "scss/subdir/multilevelimport.scss" ],' +
|
||||
'"sourcesContent": [ "@import ../inheritance;" ]' +
|
||||
'}';
|
||||
|
||||
stream = sass.sync();
|
||||
stream.on('data', function(cssFile) {
|
||||
should.exist(cssFile.sourceMap);
|
||||
cssFile.sourceMap.sources.should.eql(expectedSources);
|
||||
done();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
||||
});
|
|
@ -1,9 +0,0 @@
|
|||
table.hl {
|
||||
margin: 2em 0; }
|
||||
table.hl td.ln {
|
||||
text-align: right; }
|
||||
|
||||
li {
|
||||
font-family: serif;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em; }
|
3
test/scss/_partial.scss
Normal file
3
test/scss/_partial.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: red;
|
||||
}
|
3
test/scss/error.scss
Normal file
3
test/scss/error.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
font 'Comic Sans';
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
@import "cats";
|
|
@ -1,2 +0,0 @@
|
|||
@import "cats";
|
||||
|
|
@ -2,5 +2,5 @@ $blue: #3bbfce;
|
|||
$margin: 16px;
|
||||
|
||||
body {
|
||||
background: pink;
|
||||
background: pink;
|
||||
}
|
||||
|
|
5
test/scss/includes/_dogs.sass
Normal file
5
test/scss/includes/_dogs.sass
Normal file
|
@ -0,0 +1,5 @@
|
|||
$blue: #3bbfce;
|
||||
$margin: 16px;
|
||||
|
||||
footer
|
||||
background: red;
|
4
test/scss/indent.sass
Normal file
4
test/scss/indent.sass
Normal file
|
@ -0,0 +1,4 @@
|
|||
$color: blue
|
||||
|
||||
body .div
|
||||
color: $color
|
|
@ -1,4 +1,5 @@
|
|||
@import "includes/cats";
|
||||
@import "includes/dogs";
|
||||
|
||||
.error {
|
||||
border: #f00;
|
||||
|
@ -13,4 +14,4 @@
|
|||
.badError {
|
||||
@extend .error;
|
||||
border-width: 3px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
table.hl {
|
||||
margin: 2em 0;
|
||||
td.ln {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
font: {
|
||||
family: serif;
|
||||
weight: bold;
|
||||
size: 1.2em;
|
||||
}
|
||||
}
|
1
test/scss/subdir/multilevelimport.scss
vendored
1
test/scss/subdir/multilevelimport.scss
vendored
|
@ -1 +0,0 @@
|
|||
@import "../inheritance";
|
|
@ -11,4 +11,4 @@ $margin: 16px;
|
|||
padding: $margin / 2;
|
||||
margin: $margin / 2;
|
||||
border-color: $blue;
|
||||
}
|
||||
}
|
||||
|
|
200
test/test.js
200
test/test.js
|
@ -1,200 +0,0 @@
|
|||
var assert = require('assert');
|
||||
var gsass = require('../');
|
||||
var gutil = require('gulp-util');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var test = require('tape');
|
||||
|
||||
function createVinyl(sassFileName, contents, base) {
|
||||
base = base || path.join(__dirname, 'scss');
|
||||
var filePath = path.join(base, sassFileName);
|
||||
|
||||
return new gutil.File({
|
||||
cwd: __dirname,
|
||||
base: base,
|
||||
path: filePath,
|
||||
contents: contents || fs.readFileSync(filePath)
|
||||
});
|
||||
}
|
||||
|
||||
test('pass file when isNull()', function (t) {
|
||||
var stream = gsass();
|
||||
var emptyFile = {
|
||||
isNull: function () { return true; }
|
||||
};
|
||||
stream.on('data', function (data) {
|
||||
t.equal(data, emptyFile);
|
||||
t.end();
|
||||
});
|
||||
stream.write(emptyFile);
|
||||
});
|
||||
|
||||
// test('emit error when file isStream()', function (t) {
|
||||
// var stream = gsass();
|
||||
// var streamFile = {
|
||||
// isNull: function () { return false; },
|
||||
// isStream: function () { return true; }
|
||||
// };
|
||||
// stream.on()
|
||||
// });
|
||||
|
||||
test('compile a single sass file', function (t) {
|
||||
var sassFile = createVinyl('mixins.scss');
|
||||
|
||||
var stream = gsass();
|
||||
stream.on('data', function (cssFile) {
|
||||
t.ok(cssFile, 'cssFile should exist');
|
||||
t.ok(cssFile.path, 'cssFile.path should exist');
|
||||
t.ok(cssFile.relative, 'cssFile.relative should exist');
|
||||
t.ok(cssFile.contents, 'cssFile.contents should exist');
|
||||
t.equal(cssFile.path, path.join(__dirname, 'scss', 'mixins.css'));
|
||||
t.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'ref/mixins.css'), 'utf8'),
|
||||
cssFile.contents.toString(),
|
||||
'file compiles correctly to css'
|
||||
);
|
||||
t.end();
|
||||
})
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
test('compile a single sass file synchronously', function (t) {
|
||||
var sassFile = createVinyl('mixins.scss');
|
||||
|
||||
var stream = gsass({sync: true});
|
||||
stream.on('data', function (cssFile) {
|
||||
t.ok(cssFile, 'cssFile should exist');
|
||||
t.ok(cssFile.path, 'cssFile.path should exist');
|
||||
t.ok(cssFile.relative, 'cssFile.relative should exist');
|
||||
t.ok(cssFile.contents, 'cssFile.contents should exist');
|
||||
t.equal(cssFile.path, path.join(__dirname, 'scss', 'mixins.css'));
|
||||
t.equal(
|
||||
fs.readFileSync(path.join(__dirname, 'ref/mixins.css'), 'utf8'),
|
||||
cssFile.contents.toString(),
|
||||
'file compiles correctly to css'
|
||||
);
|
||||
t.end();
|
||||
})
|
||||
stream.write(sassFile);
|
||||
});
|
||||
|
||||
test('compile multiple sass files', function (t) {
|
||||
var files = [
|
||||
createVinyl('inheritance.scss'),
|
||||
createVinyl('mixins.scss'),
|
||||
createVinyl('nesting.scss'),
|
||||
createVinyl('variables.scss')
|
||||
];
|
||||
|
||||
t.plan(files.length * 4);
|
||||
var stream = gsass();
|
||||
|
||||
stream.on('data', function (cssFile) {
|
||||
t.ok(cssFile, 'cssFile exists');
|
||||
t.ok(cssFile.path, 'cssFile.path exists');
|
||||
t.ok(cssFile.relative, 'cssFile.relative exists');
|
||||
t.ok(cssFile.contents, 'cssFile.contents exists');
|
||||
});
|
||||
|
||||
files.forEach(function (file) {
|
||||
stream.write(file);
|
||||
});
|
||||
});
|
||||
|
||||
test('compile multiple sass files with includePaths', function (t) {
|
||||
var files = [
|
||||
createVinyl('file1.scss', null, path.join(__dirname, 'scss', 'include-path-tests')),
|
||||
createVinyl('file2.scss', null, path.join(__dirname, 'scss', 'include-path-tests'))
|
||||
];
|
||||
var options = {
|
||||
includePaths: [path.resolve(__dirname, 'scss', 'includes')]
|
||||
};
|
||||
|
||||
t.plan(files.length * 4);
|
||||
var stream = gsass(options);
|
||||
|
||||
stream.on('data', function (cssFile) {
|
||||
t.ok(cssFile, 'cssFile exists');
|
||||
t.ok(cssFile.path, 'cssFile.path exists');
|
||||
t.ok(cssFile.relative, 'cssFile.relative exists');
|
||||
t.ok(cssFile.contents, 'cssFile.contents exists');
|
||||
});
|
||||
|
||||
files.forEach(function (file) {
|
||||
stream.write(file);
|
||||
});
|
||||
});
|
||||
|
||||
test('emit error on sass errors', function (t) {
|
||||
var stream = gsass();
|
||||
var errorFile = createVinyl('somefile.sass',
|
||||
new Buffer('body { font \'Comic Sans\'; }'));
|
||||
stream.on('error', function (err) {
|
||||
t.equal(err.message,
|
||||
'property "font" must be followed by a \':\''
|
||||
);
|
||||
t.end();
|
||||
});
|
||||
stream.write(errorFile);
|
||||
});
|
||||
|
||||
test('emit error on sass errors when using sync true', function (t) {
|
||||
var stream = gsass({sync: true});
|
||||
var errorFile = createVinyl('somefile.sass',
|
||||
new Buffer('body { font \'Comic Sans\'; }'));
|
||||
stream.on('error', function (err) {
|
||||
t.equal(err.message,
|
||||
'property "font" must be followed by a \':\''
|
||||
);
|
||||
t.end();
|
||||
});
|
||||
stream.write(errorFile);
|
||||
});
|
||||
|
||||
test('call custom error callback when opts.onError is given', function (t) {
|
||||
var stream = gsass({ onError: function (err) {
|
||||
t.equal(err.message,
|
||||
'property "font" must be followed by a \':\''
|
||||
);
|
||||
t.end();
|
||||
}});
|
||||
|
||||
var errorFile = createVinyl('somefile.sass',
|
||||
new Buffer('body { font \'Comic Sans\'; }'));
|
||||
|
||||
stream.write(errorFile);
|
||||
});
|
||||
|
||||
test('sourcemaps', function (t) {
|
||||
var sassFile = createVinyl('subdir/multilevelimport.scss');
|
||||
|
||||
// Pretend sourcemap.init() happened by mimicking
|
||||
// the object it would create.
|
||||
|
||||
sassFile.sourceMap = '{' +
|
||||
'"version": 3,' +
|
||||
'"file": "scss/subdir/multilevelimport.scss",' +
|
||||
'"names": [],' +
|
||||
'"mappings": "",' +
|
||||
'"sources": [ "scss/subdir/multilevelimport.scss" ],' +
|
||||
'"sourcesContent": [ "@import ../inheritance;" ]' +
|
||||
'}';
|
||||
|
||||
// Expected sources are relative to file.base
|
||||
var expectedSources = [
|
||||
'includes/_cats.scss',
|
||||
'inheritance.scss'
|
||||
];
|
||||
|
||||
var stream = gsass();
|
||||
|
||||
stream.on('data', function (cssFile) {
|
||||
t.deepEqual(
|
||||
cssFile.sourceMap.sources,
|
||||
expectedSources,
|
||||
'sourcemap paths are relative to file.base'
|
||||
);
|
||||
t.end();
|
||||
});
|
||||
stream.write(sassFile);
|
||||
});
|
Loading…
Reference in a new issue