diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8f9d77e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{package.json,*.yml}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af41131 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +lib/ +coverage/ +.nyc_output/ +npm-debug.log +*.sublime* diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..a7b135a --- /dev/null +++ b/.npmignore @@ -0,0 +1,5 @@ +node_modules/ +src/ +.gitignore +.travis.yml +coverage/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d30a2a8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +sudo: false +language: node_js +node_js: + - "5.1.0" + - "4.2.2" + +after_script: + - './node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e569059 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,71 @@ +## [0.0.17] - 18-03-2016 +### Added +- Added #1, ava +- Added #19, coverage to travis config +- Adeed test after transpiling + +### Change +- Change #21, isparta to nyc +- Rename index.es6 to index +- Update #28, move updtr to prepublish +- Change #1, test to ava +- Update #31, matcher and core + +### Removed +- Removed #30, ild node version in .travis config +- Removed #1, mocha chai +- Remove #19, coverage runs in package.json +- Remove config for babel from cli + +### Fixed +- Fixed report coverage + +## [0.0.17] - 15-03-2016 +### Added +- Added #18, babel config to package.json +- Added #27, updtr + +### Change +- Update gitignore, added sublime config +- Update #23, change name run compile to build +- Update #24, update runers +- Update #25, devDep +- Change #20, babel-core to babel-register +- Change #26, es2015 to node5 + +### Removed +- Remove #22, babel-runtime, not need +- Remove #18, .babelrc to package json + +### Fixed +- Fixed xo report error + +## [0.0.16] - 08-02-2016 +### Added +- Added #11, test if not variables + +### Fixed +- Fixed #13, not removes and creates lib folder +- Fixed #14, if not variables, return undefined + +## [0.0.15] - 01-02-2016 +### Fixed +- Fixed #10, Wrong loop syntax + +## [0.0.14] - 22-01-2016 +### Change +- update xo to v0.12.1 +- compile run + +## [0.0.13] - 26-12-2015 +### Change +- update lodash to v4.* + +## [0.0.12] - 26-12-2015 +### Added +- CHANGELOG.md + +## [0.0.12] - 20-12-2015 +### Added +- .editconfig + diff --git a/README.md b/README.md index 12da648..319bb41 100644 --- a/README.md +++ b/README.md @@ -1 +1,111 @@ -# postcss-attribute-selector-prefix \ No newline at end of file +# postcss-attribute-selector-prefix plugin for postcss +[![Build Status](https://img.shields.io/travis/GitScrum/postcss-attribute-selector-prefix.svg?style=flat-square)](https://travis-ci.org/GitScrum/postcss-attribute-selector-prefix)[![npm version](https://img.shields.io/npm/v/postcss-attribute-selector-prefix.svg?style=flat-square)](https://www.npmjs.com/package/postcss-attribute-selector-prefix)[![Dependency Status](https://david-dm.org/gitscrum/postcss-attribute-selector-prefix.svg?style=flat-square)](https://david-dm.org/gitscrum/postcss-attribute-selector-prefix)[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg?style=flat-square)](https://github.com/sindresorhus/xo)[![Coveralls status](https://img.shields.io/coveralls/GitScrum/postcss-attribute-selector-prefix.svg?style=flat-square)](https://coveralls.io/r/GitScrum/postcss-attribute-selector-prefix) + +[![npm downloads](https://img.shields.io/npm/dm/postcss-attribute-selector-prefix.svg?style=flat-square)](https://www.npmjs.com/package/postcss-attribute-selector-prefix)[![npm](https://img.shields.io/npm/dt/postcss-attribute-selector-prefix.svg?style=flat-square)](https://www.npmjs.com/package/postcss-attribute-selector-prefix) + +```css +/* input.css */ +.class, +[type="text"], +[class*="lorem"] { + color:red; +} +``` + +```css +/* Output example */ +.class, +[type="text"], +[class*="test-lorem"] { + color:red; +} +``` + +## Installation + +```console +$ npm install postcss-attribute-selector-prefix +``` + +## Usage +Use postcss-attribute-selector-prefix before you at-rules plugin + +```js +// dependencies +var fs = require("fs"); +var postcss = require("postcss"); +var attrSelector = require("postcss-attribute-selector-prefix"); + +// css to be processed +var css = fs.readFileSync("css/input.css", "utf8"); + +// process css +var output = postcss() + .use(attrSelector({ prefix: 'test-' })) + .css; + +console.log(output); +``` + +### Options + +#### `prefix` + +Type: `string` +Default: `` + +#### `filter` +*attribute selector to which we must add the prefix* + +Type: `Array` +Default: `[]` +Example: `['class', 'id']` + +```css +/* input.css */ +.class, +[type="text"], +[class*="lorem"], +[id^="myID"] { + color: red; +} +``` + +```css +/* Output example */ +.class, +[type="text"], +[class*="test-lorem"], +[id^="test-myID"] { + color: red; +} +``` + +#### `ignore` +*ignored attribute selector* + +Type: `Array` +Default: `[]` +Example: `['type', 'alt']` + +```css +/* input.css */ +.class, +[type="text"], +[alt*="ALT"], +[class*="class"] { + color: red; +} +``` + +```css +/* Output example */ +.class, +[type="text"], +[alt*="ALT"], +[class*="test-class"] { + color: red; +} +``` + +See [PostCSS](https://github.com/postcss/postcss) docs for examples for your environment. diff --git a/package.json b/package.json new file mode 100644 index 0000000..3560800 --- /dev/null +++ b/package.json @@ -0,0 +1,49 @@ +{ + "name": "postcss-attribute-selector-prefix", + "version": "0.0.0", + "description": "A attribute selector prefixer for postcss", + "main": "./lib/index.js", + "scripts": { + "test": "xo ./src/*.js ./test/*.js && nyc ava", + "clean": "rm -rf lib && mkdir lib", + "build": "npm run clean && babel src/index.js --out-file lib/index.js && npm t" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/GitScrum/postcss-attribute-selector-prefix.git" + }, + "keywords": [ + "postcss", + "postcss-plugin", + "prefix", + "css" + ], + "author": "Scrum", + "license": "MIT", + "bugs": { + "url": "https://github.com/GitScrum/postcss-attribute-selector-prefix/issues" + }, + "homepage": "https://github.com/GitScrum/postcss-attribute-selector-prefix#readme", + "babel": { + "presets": [ + "node5" + ] + }, + "ava": { + "require": [ + "babel-register" + ] + }, + "dependencies": { + "postcss": "^5.0.19" + }, + "devDependencies": { + "ava": "^0.13.0", + "babel-cli": "^6.6.5", + "babel-preset-node5": "^11.0.0", + "babel-register": "^6.7.2", + "coveralls": "^2.11.8", + "nyc": "^6.1.1", + "xo": "^0.13.0" + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..4749414 --- /dev/null +++ b/src/index.js @@ -0,0 +1,27 @@ +import postcss from 'postcss'; + +const filter = (filter, attributeSelector) => new RegExp(filter.map(attribut => `^\\[${attribut}`).join('|')).test(attributeSelector); + +export default postcss.plugin('postcss-attribute-selector-prefix', options => { + return nodes => { + return nodes.walkRules(rule => { + rule.selector = rule.selector.replace(/\[.*?\]/g, (match) => { + if (options.prefix === undefined) { + return match; + } + + if (options.filter !== undefined && filter(options.filter, match) === false) { + return match; + } + + if (options.ignore !== undefined && filter(options.ignore, match) === true) { + return match; + } + + return match.replace(/(\[.*?="?)(.*?)("?\])/, (match, before, required, after) => { + return `${before}${options.prefix}${required}${after}`; + }); + }); + }); + }; +}); diff --git a/test/test-plugin.js b/test/test-plugin.js new file mode 100644 index 0000000..b6086f8 --- /dev/null +++ b/test/test-plugin.js @@ -0,0 +1,53 @@ +import test from 'ava'; +import postcss from 'postcss'; +import plugin from '../src/'; + +const processing = (inputCSS, options) => postcss([plugin(options)]).process(inputCSS).css; + +test('processing not options and not attribute selector', t => { + const expected = '.class, .test { color:red; }'; + const fixtures = '.class, .test { color:red; }'; + t.is(processing(fixtures), expected); +}); + +test('processing options prefix and not attribute selector', t => { + const expected = '.class { color:red; }'; + const fixtures = '.class { color:red; }'; + t.is(processing(fixtures, {prefix: 'test-'}), expected); +}); + +test('processing options prefix and attribute selector', t => { + const expected = '.class, [type="test-text"] { color:red; }'; + const fixtures = '.class, [type="text"] { color:red; }'; + t.is(processing(fixtures, {prefix: 'test-'}), expected); +}); + +test('processing options prefix, filter and attribute selector', t => { + const expected = '.class, [type="text"], [class*="test-lorem"] { color:red; }'; + const fixtures = '.class, [type="text"], [class*="lorem"] { color:red; }'; + t.is(processing(fixtures, {prefix: 'test-', filter: ['class']}), expected); +}); + +test('processing options prefix, filter and attribute selector', t => { + const expected = '.class, [type="text"], [alt*="class"] { color:red; }'; + const fixtures = '.class, [type="text"], [alt*="class"] { color:red; }'; + t.is(processing(fixtures, {prefix: 'test-', filter: ['class']}), expected); +}); + +test('processing options filter and attribute selector', t => { + const expected = '.class, [type="text"], [class*="lorem"] { color:red; }'; + const fixtures = '.class, [type="text"], [class*="lorem"] { color:red; }'; + t.is(processing(fixtures, {filter: ['class']}), expected); +}); + +test('processing options prefix, filter, ignore and attribute selector', t => { + const expected = '.class, [type="text"], [class*="lorem"] { color:red; }'; + const fixtures = '.class, [type="text"], [class*="lorem"] { color:red; }'; + t.is(processing(fixtures, {prefix: 'test', filter: ['class'], ignore: ['class']}), expected); +}); + +test('processing options prefix, ignore and attribute selector', t => { + const expected = '.class, [type="text"], [class*="test-lorem"] { color:red; }'; + const fixtures = '.class, [type="text"], [class*="lorem"] { color:red; }'; + t.is(processing(fixtures, {prefix: 'test-', ignore: ['type']}), expected); +});