├── .editorconfig ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── package.json └── test └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | quote_type = single 11 | 12 | [*.{json,yml}] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | - push 4 | - pull_request 5 | jobs: 6 | test: 7 | name: Node.js ${{ matrix.node-version }} 8 | runs-on: ubuntu-latest 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | node-version: 13 | - 17 14 | - 14 15 | - 12 16 | steps: 17 | - uses: actions/checkout@v2 18 | - uses: actions/setup-node@v1 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | - run: npm install 22 | - run: npm test 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | 3 | node_modules/ 4 | 5 | test/ 6 | .travis.yml 7 | 8 | gulpfile.js 9 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### Changelog 2 | 3 | All notable changes to this project will be documented in this file. Dates are displayed in UTC. 4 | 5 | #### v3.0.0 6 | 7 | > 2 July 2022 8 | 9 | - Added object-merge module [`#3`](https://github.com/johnie/postcss-crip/pull/3) 10 | - Fixed syntax for second js example [`#1`](https://github.com/johnie/postcss-crip/pull/1) 11 | - feat: Update plugin to use PostCSS 8 [`7ee5393`](https://github.com/johnie/postcss-crip/commit/7ee53938c2d7d5e182191582d6bd9cfce7abfad5) 12 | - Initial commit [`fea7d92`](https://github.com/johnie/postcss-crip/commit/fea7d92571ffe9cd33b20cb53aa8f55d394d01ef) 13 | - First release [`0205471`](https://github.com/johnie/postcss-crip/commit/0205471126332e35e2bedf309a563410e9c97ae3) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2015 Johnie Hjelm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostCSS Crip [![Build Status][ci-img]][ci] 2 | 3 | [PostCSS] plugin Shorthand properties for Crips that are too lazy to write. 4 | 5 | [postcss]: https://github.com/postcss/postcss 6 | [ci-img]: https://github.com/johnie/postcss-crip/actions/workflows/main.yml/badge.svg 7 | [ci]: https://travis-ci.org/johnie/postcss-crip 8 | 9 | ## Installation 10 | 11 | ```console 12 | $ npm install postcss-crip --save-dev 13 | ``` 14 | 15 | ### Quick Start 16 | 17 | ```js 18 | // Dependencies 19 | const fs = require('fs'); 20 | const postcss = require('postcss'); 21 | const crip = require('postcss-crip'); 22 | 23 | // CSS to be processed 24 | const css = fs.readFileSync('input.css', 'utf8'); 25 | 26 | // Process our crip css using postcss-crip 27 | const output = postcss().use(crip()).process(css).css; 28 | 29 | console.log('\n===>Output CSS:\n', output); 30 | ``` 31 | 32 | Or just: 33 | 34 | ```js 35 | const output = postcss(crip()).process(css).css; 36 | ``` 37 | 38 | **Input:** 39 | 40 | ```css 41 | /* Input example */ 42 | body { 43 | f: 24px/16px red normal Helvetica, serif; 44 | bg: #000 url('holy/crip/its/a/crapple.png') top left no-repeat; 45 | bgz: cover; 46 | } 47 | 48 | .crip { 49 | w: 100px; 50 | h: 100px; 51 | pos: relative; 52 | p: 10px; 53 | m: 20px; 54 | } 55 | ``` 56 | 57 | **Output:** 58 | 59 | ```css 60 | /* Output example */ 61 | body { 62 | font: 24px/16px red normal Helvetica, serif; 63 | background: #000 url('holy/crip/its/a/crapple.png') top left no-repeat; 64 | background-size: cover; 65 | } 66 | 67 | .crip { 68 | width: 100px; 69 | height: 100px; 70 | position: relative; 71 | padding: 10px; 72 | margin: 20px; 73 | } 74 | ``` 75 | 76 | #### [See the full list of abbreviations](https://github.com/johnie/crip-css-properties) 77 | 78 | ## Options 79 | 80 | _(default: `{}`)_ 81 | 82 | You can create your own crip properties. Not all CSS properties are available in the module. So feel free to add your own. 83 | 84 | ```js 85 | const options = { 86 | az: ['azimuth'], 87 | }; 88 | 89 | const output = postcss(crip(options)).process(css).css; 90 | ``` 91 | 92 | **input.css** 93 | 94 | ```css 95 | td { 96 | az: far-right; 97 | } 98 | ``` 99 | 100 | **output.css** 101 | 102 | ```css 103 | td { 104 | azimuth: far-right; 105 | } 106 | ``` 107 | 108 | ## [Changelog](CHANGELOG.md) 109 | 110 | ## [License](LICENSE) 111 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const objectMerge = require('object-merge'); 2 | const DEFAULTS = require('crip-css-properties'); 3 | 4 | const postcssCrip = (opts = {}) => { 5 | let PROPS = objectMerge(DEFAULTS, opts); 6 | 7 | return { 8 | postcssPlugin: 'postcss-crip', 9 | Once(root) { 10 | root.walkRules((rule) => { 11 | rule.each((decl) => { 12 | let { prop } = decl; 13 | 14 | if (!Object.prototype.hasOwnProperty.call(PROPS, prop)) return; 15 | 16 | let properties = PROPS[prop]; 17 | 18 | properties.forEach((property, index) => { 19 | decl.cloneBefore({ 20 | prop: properties[index], 21 | value: decl.value, 22 | }); 23 | }); 24 | 25 | decl.remove(); 26 | }); 27 | }); 28 | }, 29 | }; 30 | }; 31 | 32 | module.exports.postcss = true; 33 | module.exports = postcssCrip; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postcss-crip", 3 | "version": "3.0.0", 4 | "description": "PostCSS plugin Shorthand properties for Crips too lazy to write", 5 | "keywords": [ 6 | "postcss", 7 | "css", 8 | "postcss-plugin", 9 | "shorthand", 10 | "crip" 11 | ], 12 | "engines": { 13 | "node": ">=6.0.0" 14 | }, 15 | "author": "Johnie Hjelm ", 16 | "license": "MIT", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/johnie/postcss-crip.git" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/johnie/postcss-crip/issues" 23 | }, 24 | "homepage": "https://github.com/johnie/postcss-crip", 25 | "dependencies": { 26 | "crip-css-properties": "^1.0.1", 27 | "object-merge": "^2.5.1", 28 | "postcss": "^8.4.14" 29 | }, 30 | "devDependencies": { 31 | "clean-publish": "^4.0.1", 32 | "eslint": "^8.19.0", 33 | "eslint-config-postcss": "^4.0.0", 34 | "husky": "^8.0.1", 35 | "jest": "^28.1.2", 36 | "lint-staged": "^13.0.3" 37 | }, 38 | "scripts": { 39 | "test": "jest" 40 | }, 41 | "lint-staged": { 42 | "*.js": "eslint *.js" 43 | }, 44 | "eslintConfig": { 45 | "extends": "eslint-config-postcss", 46 | "rules": { 47 | "max-len": "off" 48 | }, 49 | "env": { 50 | "jest": true 51 | } 52 | }, 53 | "clean-publish": { 54 | "cleanDocs": true 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const postcss = require('postcss'); 2 | 3 | const plugin = require('../'); 4 | 5 | const test = (input, output, opts, done) => { 6 | postcss([plugin(opts)]) 7 | .process(input, { from: undefined }) 8 | .then((result) => { 9 | expect(result.css).toEqual(output); 10 | expect(result.warnings()).toStrictEqual([]); 11 | done(); 12 | }) 13 | .catch((error) => { 14 | done(error); 15 | }); 16 | }; 17 | 18 | describe('postcss-crip', () => { 19 | it('handles background', (done) => { 20 | test('h1 { bg: #000; }', 'h1 { background: #000; }', {}, done); 21 | }); 22 | 23 | it('handles background-color', (done) => { 24 | test('h1 { bgc: red; }', 'h1 { background-color: red; }', {}, done); 25 | }); 26 | 27 | it('handles background-size', (done) => { 28 | test('h1 { bgz: cover; }', 'h1 { background-size: cover; }', {}, done); 29 | }); 30 | 31 | it('handles border', (done) => { 32 | test( 33 | 'h1 { bd: 1px solid red; }', 34 | 'h1 { border: 1px solid red; }', 35 | {}, 36 | done 37 | ); 38 | }); 39 | 40 | it('handles bottom', (done) => { 41 | test('h1 { b: 10px; }', 'h1 { bottom: 10px; }', {}, done); 42 | }); 43 | 44 | it('handles color', (done) => { 45 | test('h1 { c: red; }', 'h1 { color: red; }', {}, done); 46 | }); 47 | 48 | it('handles display', (done) => { 49 | test('h1 { d: block; }', 'h1 { display: block; }', {}, done); 50 | }); 51 | 52 | it('handles float', (done) => { 53 | test('h1 { fl: left; }', 'h1 { float: left; }', {}, done); 54 | }); 55 | 56 | it('handles font', (done) => { 57 | test( 58 | 'h1 { f: 16px/14px Helvetica, serif red; }', 59 | 'h1 { font: 16px/14px Helvetica, serif red; }', 60 | {}, 61 | done 62 | ); 63 | }); 64 | 65 | it('handles font-family', (done) => { 66 | test( 67 | 'h1 { ff: Helvetica, serif; }', 68 | 'h1 { font-family: Helvetica, serif; }', 69 | {}, 70 | done 71 | ); 72 | }); 73 | 74 | it('handles font-size', (done) => { 75 | test('h1 { fz: 12px; }', 'h1 { font-size: 12px; }', {}, done); 76 | }); 77 | 78 | it('handles font-style', (done) => { 79 | test('h1 { fs: italic; }', 'h1 { font-style: italic; }', {}, done); 80 | }); 81 | 82 | it('handles font-weight', (done) => { 83 | test('h1 { fw: bold; }', 'h1 { font-weight: bold; }', {}, done); 84 | }); 85 | 86 | it('handles height', (done) => { 87 | test('h1 { h: 10px; }', 'h1 { height: 10px; }', {}, done); 88 | }); 89 | 90 | it('handles left', (done) => { 91 | test('h1 { l: 10px; }', 'h1 { left: 10px; }', {}, done); 92 | }); 93 | 94 | it('handles letter-spacing', (done) => { 95 | test('h1 { ls: 10px; }', 'h1 { letter-spacing: 10px; }', {}, done); 96 | }); 97 | 98 | it('handles line-height', (done) => { 99 | test('h1 { lh: 10px; }', 'h1 { line-height: 10px; }', {}, done); 100 | }); 101 | 102 | it('handles list-style', (done) => { 103 | test('h1 { li-s: inside; }', 'h1 { list-style: inside; }', {}, done); 104 | }); 105 | 106 | it('handles max-height', (done) => { 107 | test('h1 { mah: 10px; }', 'h1 { max-height: 10px; }', {}, done); 108 | }); 109 | 110 | it('handles min-height', (done) => { 111 | test('h1 { mih: 10px; }', 'h1 { min-height: 10px; }', {}, done); 112 | }); 113 | 114 | it('handles max-width', (done) => { 115 | test('h1 { maw: 10px; }', 'h1 { max-width: 10px; }', {}, done); 116 | }); 117 | 118 | it('handles min-width', (done) => { 119 | test('h1 { miw: 10px; }', 'h1 { min-width: 10px; }', {}, done); 120 | }); 121 | 122 | it('handles margin', (done) => { 123 | test('h1 { m: 10px; }', 'h1 { margin: 10px; }', {}, done); 124 | }); 125 | 126 | it('handles margin-top', (done) => { 127 | test('h1 { mt: 10px; }', 'h1 { margin-top: 10px; }', {}, done); 128 | }); 129 | 130 | it('handles margin-right', (done) => { 131 | test('h1 { mr: 10px; }', 'h1 { margin-right: 10px; }', {}, done); 132 | }); 133 | 134 | it('handles margin-bottom', (done) => { 135 | test('h1 { mb: 10px; }', 'h1 { margin-bottom: 10px; }', {}, done); 136 | }); 137 | 138 | it('handles margin-left', (done) => { 139 | test('h1 { ml: 10px; }', 'h1 { margin-left: 10px; }', {}, done); 140 | }); 141 | 142 | it('handles padding', (done) => { 143 | test('h1 { p: 10px; }', 'h1 { padding: 10px; }', {}, done); 144 | }); 145 | 146 | it('handles padding-top', (done) => { 147 | test('h1 { pt: 10px; }', 'h1 { padding-top: 10px; }', {}, done); 148 | }); 149 | 150 | it('handles padding-right', (done) => { 151 | test('h1 { pr: 10px; }', 'h1 { padding-right: 10px; }', {}, done); 152 | }); 153 | 154 | it('handles padding-bottom', (done) => { 155 | test('h1 { pb: 10px; }', 'h1 { padding-bottom: 10px; }', {}, done); 156 | }); 157 | 158 | it('handles padding-left', (done) => { 159 | test('h1 { pl: 10px; }', 'h1 { padding-left: 10px; }', {}, done); 160 | }); 161 | 162 | it('handles right', (done) => { 163 | test('h1 { r: 10px; }', 'h1 { right: 10px; }', {}, done); 164 | }); 165 | 166 | it('handles text-align', (done) => { 167 | test('h1 { ta: left; }', 'h1 { text-align: left; }', {}, done); 168 | }); 169 | 170 | it('handles text-decoration', (done) => { 171 | test('h1 { td: none; }', 'h1 { text-decoration: none; }', {}, done); 172 | }); 173 | 174 | it('handles text-indent', (done) => { 175 | test('h1 { ti: -9999px; }', 'h1 { text-indent: -9999px; }', {}, done); 176 | }); 177 | 178 | it('handles text-transform', (done) => { 179 | test( 180 | 'h1 { tt: uppercase; }', 181 | 'h1 { text-transform: uppercase; }', 182 | {}, 183 | done 184 | ); 185 | }); 186 | 187 | it('handles top', (done) => { 188 | test('h1 { t: 10px; }', 'h1 { top: 10px; }', {}, done); 189 | }); 190 | 191 | it('handles vertical-align', (done) => { 192 | test('h1 { va: middle; }', 'h1 { vertical-align: middle; }', {}, done); 193 | }); 194 | 195 | it('handles visibility', (done) => { 196 | test('h1 { v: hidden; }', 'h1 { visibility: hidden; }', {}, done); 197 | }); 198 | 199 | it('handles width', (done) => { 200 | test('h1 { w: 10px; }', 'h1 { width: 10px; }', {}, done); 201 | }); 202 | 203 | it('handles white-space', (done) => { 204 | test('h1 { ws: nowrap; }', 'h1 { white-space: nowrap; }', {}, done); 205 | }); 206 | 207 | it('handles z-index', (done) => { 208 | test('h1 { zi: 1000; }', 'h1 { z-index: 1000; }', {}, done); 209 | }); 210 | 211 | it('handles custom properties', (done) => { 212 | test( 213 | 'h1 { az: far-right; }', 214 | 'h1 { azimuth: far-right; }', 215 | { 216 | az: ['azimuth'], 217 | }, 218 | done 219 | ); 220 | }); 221 | }); 222 | --------------------------------------------------------------------------------