gulp-css-nbd
Advanced tools
Comparing version 0.0.2 to 1.0.0
198
index.js
var gulpUtil = require( 'gulp-util' ); | ||
var through2 = require( 'through2' ); | ||
/** | ||
* CSS nesting by directory gulp plugin | ||
*/ | ||
module.exports = function () | ||
@@ -27,11 +30,14 @@ { | ||
{ | ||
if ( isDomEntry( data ) ) | ||
if ( isSkipFile( data ) ) | ||
{ | ||
data.contents = new Buffer( | ||
getParentSelector( data ) + '\n{\n' | ||
+ String( data.contents ) | ||
+ '\n}\n' | ||
); | ||
callback(); | ||
return; | ||
} | ||
data.contents = new Buffer( | ||
getPathSelector( data ) + '\n{\n' | ||
+ String( data.contents ) | ||
+ '\n}\n' | ||
); | ||
callback( null, data ); | ||
@@ -41,47 +47,159 @@ } | ||
); | ||
}; | ||
/** | ||
* Checks whether the file should be skipped | ||
* | ||
* @param data Through2 file data | ||
* @returns Skip file? | ||
*/ | ||
function isSkipFile( data ) | ||
{ | ||
return /\/_[^\/]*$/.test( data.path ); | ||
} | ||
/** | ||
* Build CSS selector based on file path | ||
* | ||
* @param data Through2 file data | ||
* @returns CSS selector | ||
*/ | ||
function getPathSelector( data ) | ||
{ | ||
var selectors = [ '' ]; | ||
var firstEntry = true; | ||
function isDomEntry( data ) | ||
{ | ||
return /^(?:\d+_)?html/.test( | ||
data.path.substr( data.base.length ).split( '/' )[0] | ||
); | ||
} | ||
function getParentSelector( data ) | ||
{ | ||
var selector; | ||
selector = ''; | ||
data.path.substr( data.base.length ) | ||
.split( '/' ) | ||
.slice( 0, -1 ) | ||
.forEach( | ||
function ( dir, index ) | ||
pathWithoutExtension( data.path ) | ||
.substr( data.base.length ) | ||
.split( '/' ) | ||
.forEach( | ||
function ( name ) | ||
{ | ||
if ( isNotForSelector( name ) ) | ||
{ | ||
if ( index === 0 ) | ||
return; | ||
} | ||
var descendant = isDescendantSelector( name ); | ||
var combinator = ( | ||
selectors[0].length === 0 | ||
? '' | ||
: ( descendant ? ' ' : ' > ' ) | ||
); | ||
var parts = splitSelectors( | ||
descendant | ||
? name.substr( 1 ) | ||
: name | ||
); | ||
var currentSelectors = selectors.slice(); | ||
for ( var i = 0, n = parts.length; i < n; i++ ) | ||
{ | ||
var selector = combinator + parts[i]; | ||
if ( i > 0 ) | ||
{ | ||
selector += dir.replace( /^\d+_/, '' ); | ||
selectors = selectors.concat( | ||
appendToStrings( currentSelectors.slice(), selector ) | ||
); | ||
} | ||
else | ||
{ | ||
if ( isDescendantSelector( dir ) ) | ||
{ | ||
selector += dir.substr( 1 ); | ||
} | ||
else | ||
{ | ||
selector += '> ' + dir; | ||
} | ||
appendToStrings( selectors, selector ); | ||
} | ||
} | ||
); | ||
return selector; | ||
} | ||
); | ||
return selectors.join( ', ' ); | ||
} | ||
/** | ||
* Append given string to every string in array (mutates original array) | ||
* | ||
* @param strings Array of strings | ||
* @param addition String to append | ||
* @returns Array of strings | ||
*/ | ||
function appendToStrings( strings, addition ) | ||
{ | ||
for ( var i = 0, n = strings.length; i < n; i++ ) | ||
{ | ||
strings[i] += addition; | ||
} | ||
function isDescendantSelector( name ) | ||
return strings; | ||
} | ||
/** | ||
* Split string of selectors separated by comma | ||
* | ||
* @param selectors String of selectors | ||
* @returns Array of selectors | ||
*/ | ||
function splitSelectors( selectors ) | ||
{ | ||
var parts = []; | ||
var inParentheses = false; | ||
var lastPos = 0; | ||
for ( var i = 0, n = selectors.length; i < n; i++ ) | ||
{ | ||
return name.charAt( 0 ) === '!'; | ||
if ( inParentheses ) | ||
{ | ||
if ( selectors[i] === ')' ) | ||
{ | ||
inParentheses = false; | ||
} | ||
} | ||
else if ( selectors[i] === '(' ) | ||
{ | ||
inParentheses = true; | ||
} | ||
else if ( selectors[i] === ',' ) | ||
{ | ||
parts.push( selectors.slice( lastPos, i ) ); | ||
lastPos = i + 1; | ||
} | ||
} | ||
}; | ||
parts.push( selectors.slice( lastPos ) ); | ||
return parts; | ||
} | ||
/** | ||
* Returns path without file extension | ||
* | ||
* @param path File path | ||
* @returns Path without extension | ||
*/ | ||
function pathWithoutExtension( path ) | ||
{ | ||
return path.replace( /\.\w+$/, '' ); | ||
} | ||
/** | ||
* Checks whether it is descendant selector | ||
* | ||
* @param name File or directory name | ||
* @returns Descendant selector? | ||
*/ | ||
function isDescendantSelector( name ) | ||
{ | ||
return name.charAt( 0 ) === '!'; | ||
} | ||
/** | ||
* Checks that it should not be a part of the selector | ||
* | ||
* @param name File or directory name | ||
* @returns Skip from selector? | ||
*/ | ||
function isNotForSelector( name ) | ||
{ | ||
return ( | ||
( name.charAt( 0 ) === '_' ) | ||
|| ( name.indexOf( '&' ) !== -1 ) | ||
); | ||
} |
{ | ||
"name": "gulp-css-nbd", | ||
"version": "0.0.2", | ||
"version": "1.0.0", | ||
"description": "CSS nesting by directory gulp plugin", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -6,53 +6,44 @@ # gulp-css-nbd | ||
Part of [Nest-CSS methodology](https://github.com/m18ru/nest-css). | ||
Plugin for building very specific selectors by directory structure like: | ||
src/ | ||
- 010_reset/ | ||
- … | ||
- 100_globals/ | ||
- mixins/ | ||
- … | ||
- animations.less | ||
- colors.less | ||
- constants.less | ||
- fonts.less | ||
- levels.less | ||
- media.less | ||
- variables.less | ||
- 200_text/ | ||
- a.less | ||
- 300_html/ | ||
- _global/ | ||
- _constants.pcss | ||
- _text/ | ||
- a.pcss | ||
- .some-container/ | ||
- div.widget.pcss | ||
- html/ | ||
- body/ | ||
- footer/ | ||
- &.less | ||
- p.copyright.less | ||
- header/ | ||
- !_variables.less | ||
- &.less | ||
- a.logo.less | ||
- nav.main.less | ||
- main/ | ||
- form/ | ||
- ul.fields/ | ||
- &.less | ||
- li.less | ||
- li.controls.less | ||
- li.text.less | ||
- li.textarea.less | ||
- !table.less | ||
- &.less | ||
- h1.less | ||
- h2.less | ||
- ol,ul.less | ||
- p.less | ||
- &.less | ||
- nav.breadcrumbs.less | ||
- _headings/ | ||
- h1.pcss | ||
- h2.pcss | ||
- h3,h4.pcss | ||
- !table.pcss | ||
- p.pcss | ||
- &.pcss | ||
With *300_html* as entry point for building selectors like: | ||
With results like: | ||
`html > body > main table {` | ||
```css | ||
a {} | ||
.some-container > div.widget {} | ||
html > body {} | ||
html > body > main table {} | ||
html > body > main > p {} | ||
html > body > main > h1 {} | ||
html > body > main > h2 {} | ||
html > body > main > h3, html > body > main > h4 {} | ||
``` | ||
or | ||
Rules: | ||
`html > body > form > ul.fields > li.text {` | ||
- CSS files should start with `&` selector (for using selector, based on their path). | ||
- Path to file (with file name) used to build the selector. | ||
- Directories starts with `_` used only for special grouping and their name is not used in the selector. | ||
- Files starts with `_` are skipped. | ||
- Files and directories starts with `!` joined using descendant combinator, other joined using child combinator. | ||
@@ -73,3 +64,2 @@ ## Usage | ||
var concat = require( 'gulp-concat' ); | ||
var less = require( 'gulp-less' ); | ||
@@ -80,6 +70,6 @@ gulp.task( | ||
{ | ||
gulp.src( './styles/src/**/*.less' ) | ||
gulp.src( './styles/src/**/*.pcss' ) | ||
.pipe( cssNdb() ) | ||
.pipe( concat( 'common.less' ) ) | ||
.pipe( less() ) | ||
.pipe( concat( 'common.css' ) ) | ||
// Some processing (PostCSS, LESS, SCSS or any other with nesting and &) | ||
.pipe( gulp.dest( './styles/' ) ); | ||
@@ -86,0 +76,0 @@ } |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
6893
182
2
76