├── .gitignore ├── ChangeLog.md ├── README.md ├── index.js ├── package.json ├── test ├── expected-double.css ├── expected-single.css ├── input.css └── test.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # 2.1.1 2 | 3 | * Remove unused runtime dependency to minimatch 4 | * Update postcss in test to >=3.0.5 5 | 6 | ## 2.1.0 7 | 8 | * Add first-letter and first-line to the default value of the selectors option 9 | 10 | ## 2.0.0 11 | 12 | * Output the single colon selectors only, since rules containing double colon selectors are ignored by IE 8 13 | 14 | ## 1.0.0 15 | 16 | * Initial version 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # postcss-pseudoelements 2 | 3 | postcss helper for pseudo element colons, it handles double -> single and single -> double. 4 | 5 | ## Usage 6 | 7 | ### Double to Single (default) 8 | ```javascript 9 | var pe = require('postcss-pseudoelements'); 10 | var postcss = require('postcss'); 11 | var options = { 12 | single: true, // default 13 | selectors: ['before','after','first-letter','first-line'], // default 14 | }; 15 | 16 | var processor = postcss(pe(options)); 17 | 18 | console.log(processor.process('a:before {}').css) // outputs: a:before {} 19 | console.log(processor.process('a::before {}').css) // outputs: a:before {} 20 | ``` 21 | 22 | ### Single to Double 23 | 24 | ```javascript 25 | var pe = require('postcss-pseudoelements'); 26 | var postcss = require('postcss'); 27 | var options = { 28 | single: false, 29 | selectors: ['before','after','first-letter','first-line'], // default 30 | }; 31 | 32 | var processor = postcss(pe(options)); 33 | 34 | console.log(processor.process('a:before {}').css) // outputs: a::before {} 35 | console.log(processor.process('a::before {}').css) // outputs: a::before {} 36 | ``` 37 | 38 | ## Options 39 | 40 | `single`: Boolean 41 | * `true` (default) if you want to move from double colon to colon for backwards compatibility 42 | * `false` if you need double colons 43 | 44 | `selectors`: `Array` of pseudo-element selectors to rewrite with single and double colons. Note that these values will be used in a regexp without escaping. Defaults to `['before','after','first-letter','first-line']` 45 | 46 | example selectors: 47 | ``` 48 | var options = { 49 | selectors: [ 50 | 'hover', 51 | 'focus', 52 | 'active', 53 | 'after', 54 | 'ms-expand', 55 | 'not', 56 | 'first-child', 57 | 'last-child' 58 | ], 59 | }; 60 | ``` 61 | 62 | ### Defaults 63 | ```javascript 64 | var options = { 65 | single: true, 66 | [ 67 | 'before', 68 | 'after', 69 | 'first-letter', 70 | 'first-line' 71 | ] 72 | }; 73 | ``` 74 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var postcss = require('postcss'); 2 | 3 | module.exports = postcss.plugin('pseudoelements', (options) => { 4 | 5 | options = options || { single: true }; 6 | 7 | var selectors = options.selectors || [ 8 | 'before', 9 | 'after', 10 | 'first-letter', 11 | 'first-line' 12 | ] 13 | 14 | var replacements = new RegExp(':{1,}(' + selectors.join('|') + ')', 'gi'); 15 | var replaceWith = options.single ? ':$1' : '::$1' 16 | 17 | return (css) => { 18 | css.walkRules((rule) => { 19 | rule.selector = rule.selector.replace(replacements, replaceWith); 20 | }); 21 | }; 22 | }); 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postcss-pseudoelements", 3 | "version": "5.0.0", 4 | "description": "PostCSS plugin to add single-colon CSS 2.1 syntax pseudo selectors (i.e. :before)", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/axa-ch/postcss-pseudoelements" 12 | }, 13 | "keywords": [ 14 | "postcss", 15 | "postcss-plugin", 16 | "pseudoelements", 17 | "before", 18 | "after" 19 | ], 20 | "author": "Sven Tschui ", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/axa-ch/postcss-pseudoelements/issues" 24 | }, 25 | "homepage": "https://github.com/axa-ch/postcss-pseudoelements", 26 | "devDependencies": { 27 | "mocha": "^2.0.1", 28 | "should": "^5.0.0" 29 | }, 30 | "dependencies": { 31 | "postcss": "^6.0.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/expected-double.css: -------------------------------------------------------------------------------- 1 | div::before { 2 | display: block; 3 | } 4 | 5 | p::before { 6 | display: block; 7 | } 8 | 9 | a::before strong::before { 10 | display: block; 11 | } 12 | 13 | span::before em::before { 14 | display: block; 15 | } 16 | 17 | 18 | section::before article::after { 19 | display: block; 20 | } 21 | 22 | foo::before bar::after { 23 | display: block; 24 | } 25 | 26 | ::after { 27 | display: block; 28 | } 29 | 30 | ::after { 31 | display: block; 32 | } 33 | 34 | ::first-line { 35 | display: block; 36 | } 37 | 38 | ::first-letter { 39 | display: block; 40 | } 41 | 42 | ::first-line { 43 | display: block; 44 | } 45 | 46 | ::first-letter { 47 | display: block; 48 | } 49 | -------------------------------------------------------------------------------- /test/expected-single.css: -------------------------------------------------------------------------------- 1 | div:before { 2 | display: block; 3 | } 4 | 5 | p:before { 6 | display: block; 7 | } 8 | 9 | a:before strong:before { 10 | display: block; 11 | } 12 | 13 | span:before em:before { 14 | display: block; 15 | } 16 | 17 | 18 | section:before article:after { 19 | display: block; 20 | } 21 | 22 | foo:before bar:after { 23 | display: block; 24 | } 25 | 26 | :after { 27 | display: block; 28 | } 29 | 30 | :after { 31 | display: block; 32 | } 33 | 34 | :first-line { 35 | display: block; 36 | } 37 | 38 | :first-letter { 39 | display: block; 40 | } 41 | 42 | :first-line { 43 | display: block; 44 | } 45 | 46 | :first-letter { 47 | display: block; 48 | } 49 | -------------------------------------------------------------------------------- /test/input.css: -------------------------------------------------------------------------------- 1 | div:before { 2 | display: block; 3 | } 4 | 5 | p::before { 6 | display: block; 7 | } 8 | 9 | a:before strong:before { 10 | display: block; 11 | } 12 | 13 | span::before em::before { 14 | display: block; 15 | } 16 | 17 | 18 | section:before article::after { 19 | display: block; 20 | } 21 | 22 | foo::before bar:after { 23 | display: block; 24 | } 25 | 26 | ::after { 27 | display: block; 28 | } 29 | 30 | :after { 31 | display: block; 32 | } 33 | 34 | ::first-line { 35 | display: block; 36 | } 37 | 38 | ::first-letter { 39 | display: block; 40 | } 41 | 42 | :first-line { 43 | display: block; 44 | } 45 | 46 | :first-letter { 47 | display: block; 48 | } 49 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var should = require('should'); 2 | var postcss = require('postcss'); 3 | var fs = require('fs'); 4 | var pseudoelements = require('../index.js') 5 | 6 | describe('test', function() { 7 | 8 | it('should default to one colon per pseudo element', function() { 9 | var input = fs.readFileSync('./test/input.css', 'utf-8'); 10 | var expected = fs.readFileSync('./test/expected-single.css', 'utf-8'); 11 | 12 | var out = postcss(pseudoelements()).process(input); 13 | 14 | out.css.should.equal(expected, 'test failed') 15 | }); 16 | 17 | it('should default to two colons per pseudo element', function() { 18 | var input = fs.readFileSync('./test/input.css', 'utf-8'); 19 | var expected = fs.readFileSync('./test/expected-double.css', 'utf-8'); 20 | var options = { 21 | single: false, 22 | } 23 | 24 | var out = postcss(pseudoelements(options)).process(input); 25 | 26 | out.css.should.equal(expected, 'test failed') 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | ansi-styles@^3.1.0: 6 | version "3.1.0" 7 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750" 8 | dependencies: 9 | color-convert "^1.0.0" 10 | 11 | chalk@^2.0.1: 12 | version "2.0.1" 13 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" 14 | dependencies: 15 | ansi-styles "^3.1.0" 16 | escape-string-regexp "^1.0.5" 17 | supports-color "^4.0.0" 18 | 19 | color-convert@^1.0.0: 20 | version "1.9.0" 21 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" 22 | dependencies: 23 | color-name "^1.1.1" 24 | 25 | color-name@^1.1.1: 26 | version "1.1.2" 27 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d" 28 | 29 | commander@0.6.1: 30 | version "0.6.1" 31 | resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" 32 | 33 | commander@2.3.0: 34 | version "2.3.0" 35 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" 36 | 37 | debug@2.2.0: 38 | version "2.2.0" 39 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" 40 | dependencies: 41 | ms "0.7.1" 42 | 43 | diff@1.4.0: 44 | version "1.4.0" 45 | resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" 46 | 47 | escape-string-regexp@1.0.2: 48 | version "1.0.2" 49 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" 50 | 51 | escape-string-regexp@^1.0.5: 52 | version "1.0.5" 53 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 54 | 55 | glob@3.2.11: 56 | version "3.2.11" 57 | resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" 58 | dependencies: 59 | inherits "2" 60 | minimatch "0.3" 61 | 62 | growl@1.9.2: 63 | version "1.9.2" 64 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" 65 | 66 | has-flag@^2.0.0: 67 | version "2.0.0" 68 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" 69 | 70 | inherits@2: 71 | version "2.0.3" 72 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 73 | 74 | jade@0.26.3: 75 | version "0.26.3" 76 | resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" 77 | dependencies: 78 | commander "0.6.1" 79 | mkdirp "0.3.0" 80 | 81 | lru-cache@2: 82 | version "2.7.3" 83 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" 84 | 85 | minimatch@0.3: 86 | version "0.3.0" 87 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" 88 | dependencies: 89 | lru-cache "2" 90 | sigmund "~1.0.0" 91 | 92 | minimist@0.0.8: 93 | version "0.0.8" 94 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 95 | 96 | mkdirp@0.3.0: 97 | version "0.3.0" 98 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" 99 | 100 | mkdirp@0.5.1: 101 | version "0.5.1" 102 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 103 | dependencies: 104 | minimist "0.0.8" 105 | 106 | mocha@^2.0.1: 107 | version "2.5.3" 108 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" 109 | dependencies: 110 | commander "2.3.0" 111 | debug "2.2.0" 112 | diff "1.4.0" 113 | escape-string-regexp "1.0.2" 114 | glob "3.2.11" 115 | growl "1.9.2" 116 | jade "0.26.3" 117 | mkdirp "0.5.1" 118 | supports-color "1.2.0" 119 | to-iso-string "0.0.2" 120 | 121 | ms@0.7.1: 122 | version "0.7.1" 123 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" 124 | 125 | postcss@^6.0.0: 126 | version "6.0.6" 127 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.6.tgz#bba4d58e884fc78c840d1539e10eddaabb8f73bd" 128 | dependencies: 129 | chalk "^2.0.1" 130 | source-map "^0.5.6" 131 | supports-color "^4.1.0" 132 | 133 | should-equal@0.3.1: 134 | version "0.3.1" 135 | resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-0.3.1.tgz#bd8ea97a6748e39fad476a3be6fd72ebc2e72bf0" 136 | dependencies: 137 | should-type "0.0.4" 138 | 139 | should-format@0.0.7: 140 | version "0.0.7" 141 | resolved "https://registry.yarnpkg.com/should-format/-/should-format-0.0.7.tgz#1e2ef86bd91da9c2e0412335b56ababd9a2fde12" 142 | dependencies: 143 | should-type "0.0.4" 144 | 145 | should-type@0.0.4: 146 | version "0.0.4" 147 | resolved "https://registry.yarnpkg.com/should-type/-/should-type-0.0.4.tgz#0132a05417a6126866426acf116f1ed5623a5cd0" 148 | 149 | should@^5.0.0: 150 | version "5.2.0" 151 | resolved "https://registry.yarnpkg.com/should/-/should-5.2.0.tgz#9a4519b447b8b5eedce9eed96af3420d451a540b" 152 | dependencies: 153 | should-equal "0.3.1" 154 | should-format "0.0.7" 155 | should-type "0.0.4" 156 | 157 | sigmund@~1.0.0: 158 | version "1.0.1" 159 | resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" 160 | 161 | source-map@^0.5.6: 162 | version "0.5.6" 163 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" 164 | 165 | supports-color@1.2.0: 166 | version "1.2.0" 167 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" 168 | 169 | supports-color@^4.0.0, supports-color@^4.1.0: 170 | version "4.2.0" 171 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.0.tgz#ad986dc7eb2315d009b4d77c8169c2231a684037" 172 | dependencies: 173 | has-flag "^2.0.0" 174 | 175 | to-iso-string@0.0.2: 176 | version "0.0.2" 177 | resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" 178 | --------------------------------------------------------------------------------