extract-from-css
Advanced tools
Comparing version 0.4.0 to 0.4.1
var cssHelpers = require('./css-helpers'); | ||
var processSelectors = require('./process-selectors'); | ||
@@ -10,39 +11,19 @@ /** | ||
function addClassNamesFromSelectorToSet(selector, classSet) { | ||
var match, className; | ||
while (match = rClassInSelector.exec(selector)) { | ||
className = cssHelpers.unescapeIdentifier(match[1]); | ||
classSet[className] = true; | ||
} | ||
} | ||
function addClassNamesFromSelectorsToSet(selectors, classSet) { | ||
var selector; | ||
var i = 0; | ||
while (selector = selectors[i++]) { | ||
addClassNamesFromSelectorToSet(selector, classSet); | ||
} | ||
} | ||
/** | ||
* Extracts class names from CSS rules (as AST) | ||
* @param {Object} rules | ||
* @return {Array.<string>} list of class names in those rules | ||
* @return {string[]} list of class names in those rules | ||
*/ | ||
function extractClassNamesFromRules(rules) { | ||
var rule; | ||
var classSet = {}; | ||
var i = 0; | ||
while (rule = rules[i++]) { | ||
if (rule.type === 'rule') { | ||
addClassNamesFromSelectorsToSet(rule.selectors, classSet); | ||
} else if (rule.rules) { | ||
// Add nested rules to the list | ||
// Will be checked after the current ones | ||
rules.push.apply(rules, rule.rules); | ||
function extractIdsFromRules(rules) { | ||
var idSet = {}; | ||
processSelectors(rules, function(selector) { | ||
var match, id; | ||
while (!!(match = rClassInSelector.exec(selector))) { | ||
id = cssHelpers.unescapeIdentifier(match[1]); | ||
idSet[id] = true; | ||
} | ||
} | ||
return Object.keys(classSet); | ||
}); | ||
return Object.keys(idSet); | ||
} | ||
module.exports = extractClassNamesFromRules; | ||
module.exports = extractIdsFromRules; |
var cssHelpers = require('./css-helpers'); | ||
var processSelectors = require('./process-selectors'); | ||
@@ -10,36 +11,16 @@ /** | ||
function addIdsFromSelectorToSet(selector, idSet) { | ||
var match, id; | ||
while (match = rIdInSelector.exec(selector)) { | ||
id = cssHelpers.unescapeIdentifier(match[1]); | ||
idSet[id] = true; | ||
} | ||
} | ||
function addIdsFromSelectorsToSet(selectors, idSet) { | ||
var selector; | ||
var i = 0; | ||
while (selector = selectors[i++]) { | ||
addIdsFromSelectorToSet(selector, idSet); | ||
} | ||
} | ||
/** | ||
* Extracts ids from CSS rules (as AST) | ||
* @param {Object} rules | ||
* @return {Array.<string>} list of ids in those rules | ||
* @return {string[]} list of ids in those rules | ||
*/ | ||
function extractIdsFromRules(rules) { | ||
var rule; | ||
var idSet = {}; | ||
var i = 0; | ||
while (rule = rules[i++]) { | ||
if (rule.type === 'rule') { | ||
addIdsFromSelectorsToSet(rule.selectors, idSet); | ||
} else if (rule.rules) { | ||
// Add nested rules to the list | ||
// Will be checked after the current ones | ||
rules.push.apply(rules, rule.rules); | ||
processSelectors(rules, function(selector) { | ||
var match, id; | ||
while (!!(match = rIdInSelector.exec(selector))) { | ||
id = cssHelpers.unescapeIdentifier(match[1]); | ||
idSet[id] = true; | ||
} | ||
} | ||
}); | ||
return Object.keys(idSet); | ||
@@ -46,0 +27,0 @@ } |
@@ -38,2 +38,8 @@ | ||
/** | ||
* Extract the specified features from a given code | ||
* @param {string[]} features | ||
* @param {string} code | ||
* @return {Object.<string, string[]>} For each feature, a list of matches | ||
*/ | ||
function extract(features, code) { | ||
@@ -45,5 +51,6 @@ var ast = cssParser.parse(code); | ||
var i = 0; | ||
while (feature = features[i++]) { | ||
while (!!(feature = features[i++])) { | ||
methodName = 'extract' + capitalize(feature) + 'FromRules'; | ||
if (method = extractMethods[methodName]) { | ||
method = extractMethods[methodName]; | ||
if (method) { | ||
result[feature] = method(rules); | ||
@@ -50,0 +57,0 @@ } else { |
{ | ||
"name": "extract-from-css", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "Extract information from CSS code", | ||
@@ -10,5 +10,8 @@ "main": "lib/index.js", | ||
}, | ||
"bugs": "https://github.com/rubennorte/extract-from-css/issues", | ||
"scripts": { | ||
"test": "jasmine", | ||
"benchmark": "node test/benchmark.js" | ||
"benchmark": "node test/benchmark.js", | ||
"jshint": "jshint .", | ||
"build": "npm run jshint && npm test" | ||
}, | ||
@@ -19,3 +22,4 @@ "author": "Rubén Norte <rubennorte@gmail.com>", | ||
"jasmine": "^2.1.0", | ||
"benchmark": "^1.0.0" | ||
"benchmark": "^1.0.0", | ||
"jshint": "^2.5.10" | ||
}, | ||
@@ -22,0 +26,0 @@ "dependencies": { |
@@ -58,2 +58,8 @@ # Extract from CSS | ||
To check the code: | ||
```bash | ||
npm run jshint | ||
``` | ||
## Contributing | ||
@@ -64,2 +70,3 @@ | ||
3. Commit your changes: `git commit -am 'Add some feature'` | ||
4. Check the build: `npm run build` | ||
4. Push to the branch: `git push origin my-new-feature` | ||
@@ -66,0 +73,0 @@ 5. Submit a pull request :D |
@@ -13,54 +13,43 @@ | ||
it('should extract a class name with alphabetical letters', function() { | ||
var classNames = extractClasses('.className { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['className']); | ||
var classes = extractClasses('.className { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['className']); | ||
}); | ||
it('should extract several class names with alphabetical letters', function() { | ||
var classNames = extractClasses('.className1 { prop: value; } .className2 { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['className1', 'className2']); | ||
var classes = extractClasses('.className1 { prop: value; } .className2 { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['className1', 'className2']); | ||
}); | ||
it('should not repeat class names', function() { | ||
var classNames = extractClasses('.className1 { prop: value; } .className1 { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['className1']); | ||
var classes = extractClasses('.className1 { prop: value; } .className1 { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['className1']); | ||
}); | ||
it('should extract class names with underscores', function() { | ||
var classNames = extractClasses('.class_name { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['class_name']); | ||
var classes = extractClasses('.class_name { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['class_name']); | ||
}); | ||
it('should extract class names with hyphens', function() { | ||
var classNames = extractClasses('.class-name { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['class-name']); | ||
var classes = extractClasses('.class-name { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['class-name']); | ||
}); | ||
}); | ||
describe('extract class names from nested rules', function() { | ||
it('should extract class names inside a media query', function() { | ||
var classNames = extractClasses('@media (max-width: 500px) { .className { prop: value; } }'); | ||
expect(classNames).toEqualIgnoreOrder(['className']); | ||
}); | ||
it('should extract class names inside two media queries', function() { | ||
var classNames = extractClasses('@media (max-width: 500px) { @media screen { .className { prop: value; } } }'); | ||
expect(classNames).toEqualIgnoreOrder(['className']); | ||
}); | ||
}); | ||
describe('extract complex class names', function() { | ||
it('should extract class names with single escaped characters', function() { | ||
var classNames = extractClasses('.hello-\\#-world { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['hello-#-world']); | ||
var classes = extractClasses('.hello-\\#-world { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['hello-#-world']); | ||
}); | ||
it('should extract class names with multiple escaped characters', function() { | ||
var classNames = extractClasses('.\\0000E9dition { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['édition']); | ||
var classes = extractClasses('.\\0000E9dition { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['édition']); | ||
}); | ||
it('should extract class names from multiple escaped characters with white space', function() { | ||
var classNames = extractClasses('.\\E9 dition { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['édition']); | ||
var classes = extractClasses('.\\E9 dition { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['édition']); | ||
}); | ||
it('should extract class names with unicode characters', function() { | ||
var classNames = extractClasses('.list-★-item { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['list-★-item']); | ||
var classes = extractClasses('.list-★-item { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['list-★-item']); | ||
}); | ||
@@ -71,42 +60,19 @@ }); | ||
it('should extract class names at the beginning of a complex selector', function() { | ||
var classNames = extractClasses('.class-name * > tag ~ [attr~="test"] + #identifier:hover:after { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['class-name']); | ||
var classes = extractClasses('.class-name * > tag ~ [attr~="test"] + #identifier:hover:after { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['class-name']); | ||
}); | ||
it('should extract class names at the middle of a complex selector', function() { | ||
var classNames = extractClasses('* > tag ~ [attr~="test"].class-name + #identifier:hover:after { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['class-name']); | ||
var classes = extractClasses('* > tag ~ [attr~="test"].class-name + #identifier:hover:after { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['class-name']); | ||
}); | ||
it('should extract class names at the end of a complex selector', function() { | ||
var classNames = extractClasses('* > tag ~ [attr~="test"] + #identifier:hover:after.class-name { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['class-name']); | ||
var classes = extractClasses('* > tag ~ [attr~="test"] + #identifier:hover:after.class-name { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['class-name']); | ||
}); | ||
it('should extract several class names in the same selector', function() { | ||
var classNames = extractClasses('.class-name-1.class-name { prop: value; }'); | ||
expect(classNames).toEqualIgnoreOrder(['class-name-1', 'class-name']); | ||
var classes = extractClasses('.class-name-1.class-name { prop: value; }'); | ||
expect(classes).toEqualIgnoreOrder(['class-name-1', 'class-name']); | ||
}); | ||
}); | ||
describe('ignore everthing but selectors', function() { | ||
it('should ignore class names in declaration blocks', function() { | ||
// .png looks like a class selector | ||
var classNames = extractClasses('.className { prop: url("something.png") }'); | ||
expect(classNames).toEqualIgnoreOrder(['className']); | ||
}); | ||
it('should ignore class names in regular comments', function() { | ||
var classNames = extractClasses('/* .className {} */ .className1 {}'); | ||
expect(classNames).toEqualIgnoreOrder(['className1']); | ||
}); | ||
it('should ignore class names in multi-line comments', function() { | ||
var classNames = extractClasses('/* .className {} \n .className1 {} */ .className2 {}'); | ||
expect(classNames).toEqualIgnoreOrder(['className2']); | ||
}); | ||
it('should ignore class names in comments between selectors', function() { | ||
var classNames = extractClasses('.className, /* .className1 */ .className2 {}'); | ||
expect(classNames).toEqualIgnoreOrder(['className', 'className2']); | ||
}); | ||
}); | ||
}); |
@@ -38,13 +38,2 @@ | ||
describe('extract ids from nested rules', function() { | ||
it('should extract ids inside a media query', function() { | ||
var ids = extractIds('@media (max-width: 500px) { #id { prop: value; } }'); | ||
expect(ids).toEqualIgnoreOrder(['id']); | ||
}); | ||
it('should extract ids inside two media queries', function() { | ||
var ids = extractIds('@media (max-width: 500px) { @media screen { #id { prop: value; } } }'); | ||
expect(ids).toEqualIgnoreOrder(['id']); | ||
}); | ||
}); | ||
describe('extract complex ids', function() { | ||
@@ -55,2 +44,3 @@ it('should extract ids with single escaped characters', function() { | ||
}); | ||
it('should extract ids with multiple escaped characters', function() { | ||
@@ -60,2 +50,3 @@ var ids = extractIds('#\\0000E9dition { prop: value; }'); | ||
}); | ||
it('should extract ids from multiple escaped characters with white space', function() { | ||
@@ -65,2 +56,3 @@ var ids = extractIds('#\\E9 dition { prop: value; }'); | ||
}); | ||
it('should extract ids with unicode characters', function() { | ||
@@ -77,2 +69,3 @@ var ids = extractIds('#list-★-item { prop: value; }'); | ||
}); | ||
it('should extract ids at the middle of a complex selector', function() { | ||
@@ -82,2 +75,3 @@ var ids = extractIds('* > tag ~ [attr~="test"]#id + .className:hover:after { prop: value; }'); | ||
}); | ||
it('should extract ids at the end of a complex selector', function() { | ||
@@ -87,2 +81,3 @@ var ids = extractIds('* > tag ~ [attr~="test"] + .className:hover:after#id { prop: value; }'); | ||
}); | ||
it('should extract several ids in the same selector', function() { | ||
@@ -94,25 +89,2 @@ var ids = extractIds('#id-1#id { prop: value; }'); | ||
describe('ignore everthing but selectors', function() { | ||
it('should ignore ids in declaration blocks', function() { | ||
// .png looks like a class selector | ||
var ids = extractIds('#id { prop: url("something#id.png") }'); | ||
expect(ids).toEqualIgnoreOrder(['id']); | ||
}); | ||
it('should ignore ids in regular comments', function() { | ||
var ids = extractIds('/* #id {} */ #id1 {}'); | ||
expect(ids).toEqualIgnoreOrder(['id1']); | ||
}); | ||
it('should ignore ids in multi-line comments', function() { | ||
var ids = extractIds('/* #id {} \n #id1 {} */ #id2 {}'); | ||
expect(ids).toEqualIgnoreOrder(['id2']); | ||
}); | ||
it('should ignore ids in comments between selectors', function() { | ||
var ids = extractIds('#id, /* #id1 */ #id2 {}'); | ||
expect(ids).toEqualIgnoreOrder(['id', 'id2']); | ||
}); | ||
}); | ||
}); |
@@ -40,4 +40,4 @@ | ||
} | ||
} | ||
}; | ||
module.exports = matcher; |
20
95
566889
3
716