diff --git a/README.md b/README.md index 13924a6..d310057 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,13 @@ bemstyla block__foo block__bar_baz foo__bar foo__qux ... ``` +### [Jade](http://jade-lang.com/) file support + +```sh +bemstyla header.jade +bemstyla content.jade sidebar.jade footer.jade +``` + ## Solutions with the same functionality * [Bemy](//github.com/f0rmat1k/bemy) * [TEATIME](//github.com/sullenor/teatime) diff --git a/lib/index.js b/lib/index.js index 5c096e9..1ee4d52 100644 --- a/lib/index.js +++ b/lib/index.js @@ -6,6 +6,7 @@ var _ = require('lodash'); var parser = require('./parser'); +var parserJade = require('../lib/parser-jade'); var formatFile = require('./format-file'); var formatFileDir = require('./format-file-dir'); var formatFileName = require('./format-file-name'); @@ -14,7 +15,7 @@ var creator = require('./creator'); /** * @param {String} source */ -module.exports = function (source) { +var maker = function (source) { var parsed = _.clone(parser.parse(source)); _.merge(parsed, formatFile.format()); @@ -25,3 +26,17 @@ module.exports = function (source) { creator.touch(item.file); }); }; + +/** + * @param {String} source + */ +module.exports = function (source) { + if (/\.jade$/.test(source)) { + source = parserJade.parseFile(source); + _.forEach(source, function (item) { + maker(item); + }); + } else { + maker(source); + } +}; diff --git a/lib/parser-jade.js b/lib/parser-jade.js new file mode 100644 index 0000000..ce34c0d --- /dev/null +++ b/lib/parser-jade.js @@ -0,0 +1,66 @@ +/*! + * bewbem + * Copyright(c) 2015 VovanR + * MIT Licensed + */ + +var _ = require('lodash'); +var fs = require('fs'); +var path = require('path'); +var exists = fs.existsSync || path.existsSync; + +module.exports = { + /** + * Jade source parser + * + * @param {String} source + * @return {Array} + */ + parseString: function (source) { + var result = []; + + if (_.isUndefined(source)) { + return result; + } + + source = String(source); + + if (!/\./.test(source)) { + return result; + } + + var re = /\.([^\s\.\(]+)/gm; + + var parsed = source.match(re); + parsed = _.map(parsed, function (item) { + return item.slice(1); + }); + + parsed = _.uniq(parsed); + + if (parsed.length > 0) { + result = parsed; + } + + return result; + }, + + /** + * Jade file parser + * + * @param {String} filePath + * @return {Array} + */ + parseFile: function (filePath) { + var result = []; + + if (!exists(filePath)) { + return result; + } + + var fileText = fs.readFileSync(filePath).toString(); + result = this.parseString(fileText); + + return result; + }, +}; diff --git a/test/parser-jade-test-cases.yml b/test/parser-jade-test-cases.yml new file mode 100644 index 0000000..07968ad --- /dev/null +++ b/test/parser-jade-test-cases.yml @@ -0,0 +1,61 @@ +- input: '' + output: [] + +- input: block + output: [] + +- input: .block + output: + - block + +- input: .block.block_theme_simple + output: + - block + - block_theme_simple + +- input: | + block + .block + output: + - block + +- input: | + block + .block + foo + .bar + output: + - block + - bar + +- input: | + block + .block + foo + + .bar + output: + - block + - bar + +- input: .foo.bar.foo.baz.foo + output: + - foo + - bar + - baz + +- input: | + .header.header_theme_simple + .header__side.header__side_align_left + .header__side.header__side_align_right + output: + - header + - header_theme_simple + - header__side + - header__side_align_left + - header__side_align_right + +- input: | + .progressbar__bar(style='width: 90%;') + output: + - progressbar__bar diff --git a/test/parser-jade-test.js b/test/parser-jade-test.js new file mode 100644 index 0000000..5443572 --- /dev/null +++ b/test/parser-jade-test.js @@ -0,0 +1,52 @@ +var assert = require('chai').assert; +var mockfs = require('mock-fs'); +var parserJade = require('../lib/parser-jade'); +var _ = require('lodash'); +var yaml = require('js-yaml'); +var fs = require('fs'); +var path = require('path'); + +var testData = yaml.safeLoad(fs.readFileSync('./test/parser-jade-test-cases.yml', 'utf8')); + +var TEMP_DIR = '/tmp/bemstyla'; + +describe('parserJade', function () { + it('should be `Object`', function () { + assert.isObject(parserJade); + }); + + describe('#parseString', function () { + it('should return an `Array`', function () { + assert.isArray(parserJade.parseString()); + }); + + it('should parse class names from jade text', function () { + _.forEach(testData, function (data) { + assert.deepEqual( + parserJade.parseString(data.input), + data.output + ); + }); + }); + }); + + describe('#parseFile', function () { + it('should return an empty array if file does not exists', function () { + assert.isArray(parserJade.parseFile()); + }); + + it('should parse Jade file', function () { + var mockData = {}; + + var filePath = path.join(TEMP_DIR, 'foo.jade'); + var fileText = '.foo.bar'; + mockData[filePath] = fileText; + mockfs(mockData); + + assert.deepEqual(fs.readFileSync(filePath).toString(), fileText); + assert.deepEqual(parserJade.parseFile(filePath), ['foo', 'bar']); + + mockfs.restore(); + }); + }); +});