From 7faf5651d496e45babe57452ec02dd7348edb4e2 Mon Sep 17 00:00:00 2001 From: ismamz Date: Fri, 6 May 2016 17:36:56 -0300 Subject: [PATCH] first commit --- .editorconfig | 12 ++ .gitignore | 2 + .npmignore | 7 ++ .travis.yml | 5 + CHANGELOG.md | 5 + LICENSE | 20 ++++ README.md | 95 +++++++++++++++ index.js | 115 ++++++++++++++++++ lib/aspect-ratio.js | 37 ++++++ lib/circle.js | 36 ++++++ lib/clearfix.js | 36 ++++++ lib/hd-breakpoint.js | 36 ++++++ lib/hide-visually.js | 42 +++++++ lib/horizontal-rule.js | 37 ++++++ lib/hover.js | 24 ++++ lib/no-js.js | 24 ++++ lib/reset-list.js | 40 +++++++ lib/text-hide.js | 30 +++++ lib/triangle.js | 126 ++++++++++++++++++++ lib/truncate-multiline.js | 56 +++++++++ lib/truncate.js | 29 +++++ media/logo.svg | 239 ++++++++++++++++++++++++++++++++++++++ package.json | 41 +++++++ test.js | 58 +++++++++ test/index.html | 88 ++++++++++++++ test/out.css | 158 +++++++++++++++++++++++++ test/test.css | 109 +++++++++++++++++ test/test.expect.css | 158 +++++++++++++++++++++++++ test/triangle.css | 41 +++++++ test/triangle.expect.css | 69 +++++++++++ 30 files changed, 1775 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 index.js create mode 100644 lib/aspect-ratio.js create mode 100644 lib/circle.js create mode 100644 lib/clearfix.js create mode 100644 lib/hd-breakpoint.js create mode 100644 lib/hide-visually.js create mode 100644 lib/horizontal-rule.js create mode 100644 lib/hover.js create mode 100644 lib/no-js.js create mode 100644 lib/reset-list.js create mode 100644 lib/text-hide.js create mode 100644 lib/triangle.js create mode 100644 lib/truncate-multiline.js create mode 100644 lib/truncate.js create mode 100644 media/logo.svg create mode 100644 package.json create mode 100644 test.js create mode 100644 test/index.html create mode 100644 test/out.css create mode 100644 test/test.css create mode 100644 test/test.expect.css create mode 100644 test/triangle.css create mode 100644 test/triangle.expect.css diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e2cb970 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{json,yml}] +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ca9571 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..140f99b --- /dev/null +++ b/.npmignore @@ -0,0 +1,7 @@ +.gitignore + +node_modules/ +npm-debug.log + +test.js +.travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6446018 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "5" + - "4" + - "0.12" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8c42dbf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Change Log + +# v0.1.0 + +- Initial release diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e852195 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright 2016 Ismael Martinez + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a2f2060 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# PostCSS Utility Library [![Build Status][ci-img]][ci] + +[PostCSS] plugin a collection of mixins, shortcuts, helpers and tools for your CSS. + +

+ + PostCSS Utility Library + +

+ +[PostCSS]: https://github.com/postcss/postcss +[ci-img]: https://travis-ci.org/ismamz/postcss-utilities.svg +[ci]: https://travis-ci.org/ismamz/postcss-utilities + +[postcss-utilities](http://github.io/ismamz/postcss-utilities) is a [PostCSS] plugin that have the most used mixins, shortcuts and helpers to use as native `@util` rules in yours stylesheets. + + +### What is the difference with preprocessor’s mixins libraries? + +- You don’t need extra files for mixins. +- You don’t need mixins for vendor prefixes (use [autoprefixer plugin](https://github.com/postcss/autoprefixer) for that) +- You can use LESS, SASS, pure CSS or whatever you want. + +### [See Documentation](http://ismamz.github.io/postcss-utilities) + +## Example + +### Input +```css +.truncate { + @util truncate; + width: 500px; +} + +.cfx { + @util clearfix; +} + +.box-16-9 { + background-color: #ccc; + margin-bottom: 20px; + @util aspect-ratio(16:9); +} + +.circle { + @util circle(200px, red); +} +``` + +### Output +```css +.truncate { + width: 500px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.cfx:after { + content: ''; + display: block; + clear: both; +} + +.box-16-9 { + background-color: #ccc; + margin-bottom: 20px; + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; + padding-bottom: 56.25%; +} + +.circle { + border-radius: 50%; + width: 200px; + height: 200px; + background-color: red; +} +``` + +## Usage + +```js +postcss([ require('postcss-utilities') ]) +``` + +See [PostCSS] docs for examples for your environment. + +## Contributors + +- [Andrey Sitnik](https://github.com/ai) +- [Marcus Tisäter](https://github.com/marcustisater) diff --git a/index.js b/index.js new file mode 100644 index 0000000..fb8d376 --- /dev/null +++ b/index.js @@ -0,0 +1,115 @@ +var postcss = require('postcss'); +var parser = require('postcss-value-parser'); + +// import functions +var aspectRatio = require('./lib/aspect-ratio'); +var circle = require('./lib/circle'); +var clearfix = require('./lib/clearfix'); +var hdBreakpoint = require('./lib/hd-breakpoint'); +var hideVisually = require('./lib/hide-visually'); +var horizontalRule = require('./lib/horizontal-rule'); +var hover = require('./lib/hover'); +var noJs = require('./lib/no-js'); +var resetList = require('./lib/reset-list'); +var textHide = require('./lib/text-hide'); +var triangle = require('./lib/triangle'); +var truncate = require('./lib/truncate'); +var truncateMultiline = require('./lib/truncate-multiline'); + +// list of utilities names +var names = [ + 'aspect-ratio', + 'circle', + 'clearfix', + 'hd', + 'hide-visually', + 'horizontal-rule', + 'hover', + 'no-js', + 'hr', + 'reset-list', + 'text-hide', + 'triangle', + 'truncate' +]; + +// main plugin +module.exports = postcss.plugin('postcss-utilities', function (opts) { + opts = opts || {}; + + return function (css, result) { + css.walkAtRules('util', function (util) { + // get name + var name = util.params.split(/\(/, 1)[0].trim(); + + // check if the utility is available + if (names.indexOf(name) <= -1) { + throw util.error('Unknown utility ' + name); + } + + // save the params in a args array + var args = []; + args.push(name); // name as first argument + var str = parser(util.params); + str.nodes.forEach(function (node) { + if (node.type === 'function') { + node.nodes.forEach(function (i) { + if (i.type === 'word') { + args.push(i.value); + } + }); + } + }); + + // case by case + switch (name) { + case 'truncate': + if (args.length > 1) { + truncateMultiline(util, args); + } else { + truncate(util, args); + } + break; + case 'hide-visually': + hideVisually(util, args); + break; + case 'clearfix': + clearfix(util, args); + break; + case 'text-hide': + textHide(util); + break; + case 'aspect-ratio': + if (args.length > 3) { + result.warn('Too many arguments for aspect-ratio utility.'); + } + aspectRatio(util, args); + break; + case 'hr': + horizontalRule(util, args); + break; + case 'circle': + circle(util, args); + break; + case 'triangle': + triangle(util, args); + break; + case 'reset-list': + resetList(util, args); + break; + case 'hover': + hover(util, args); + break; + case 'no-js': + noJs(util, args); + break; + case 'hd': + hdBreakpoint(util, args, postcss); + break; + default: + break; + } + }); + + }; +}); diff --git a/lib/aspect-ratio.js b/lib/aspect-ratio.js new file mode 100644 index 0000000..98083de --- /dev/null +++ b/lib/aspect-ratio.js @@ -0,0 +1,37 @@ +/** + * Aspect Ratio + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + var width = args[1]; + var height = args[2]; + + parentDecl.append({ + prop: 'position', + value: 'relative', + source: decl.source + }, { + prop: 'display', + value: 'block', + source: decl.source + }, { + prop: 'height', + value: 0, + source: decl.source + }, { + prop: 'padding', + value: 0, + source: decl.source + }, { + prop: 'overflow', + value: 'hidden', + source: decl.source + }, { + prop: 'padding-bottom', + value: height / width * 100 + '%', + source: decl.source + }); + + decl.remove(); +}; diff --git a/lib/circle.js b/lib/circle.js new file mode 100644 index 0000000..f3380cc --- /dev/null +++ b/lib/circle.js @@ -0,0 +1,36 @@ +/** + * Circle + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + var color = '#000'; + var size = '100px'; + + if (args[2]) { + color = args[2]; + } + if (args[1]) { + size = args[1]; + } + + parentDecl.append({ + prop: 'border-radius', + value: '50%', + source: decl.source + }, { + prop: 'width', + value: size, + source: decl.source + }, { + prop: 'height', + value: size, + source: decl.source + }, { + prop: 'background-color', + value: color, + source: decl.source + }); + + decl.remove(); +}; diff --git a/lib/clearfix.js b/lib/clearfix.js new file mode 100644 index 0000000..702357b --- /dev/null +++ b/lib/clearfix.js @@ -0,0 +1,36 @@ +/** + * Clear Fix + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent, + ruleSelectors = parentDecl.selectors, + newRule; + + ruleSelectors = ruleSelectors.map(function (ruleSelector) { + return ruleSelector + ':after'; + }).join(',\n'); + + newRule = parentDecl.cloneBefore({ + selector: ruleSelectors + }).removeAll(); + + newRule.append({ + prop: 'content', + value: '\'\'', + source: decl.source + }, { + prop: 'display', + value: 'block', + source: decl.source + }, { + prop: 'clear', + value: 'both', + source: decl.source + }); + + if (decl.prev() === undefined && decl.next() === undefined) { + parentDecl.remove(); + } else { + decl.remove(); + } +}; diff --git a/lib/hd-breakpoint.js b/lib/hd-breakpoint.js new file mode 100644 index 0000000..7af082c --- /dev/null +++ b/lib/hd-breakpoint.js @@ -0,0 +1,36 @@ +/** + * HD Breakpoint + */ +module.exports = function (decl, args, postcss) { + var parentDecl = decl.parent, + ruleSelectors = parentDecl.selectors, + newRule; + + var pixelRatio; + + if (args[1]) { + pixelRatio = args[1]; + } else { + pixelRatio = 2; + } + + var rule = postcss.rule({ + selector: ruleSelectors, + nodes: decl.nodes, + raws: { + before: '\n ', + } + }); + + var atRule = postcss.atRule({ + name: "media", + params: '(-o-min-device-pixel-ratio: ' + pixelRatio + + '), (-webkit-min-device-pixel-ratio: ' + pixelRatio + + '), (min-resolution: 192dpi)', + }) + + atRule.append(rule); + parentDecl.parent.append(atRule); + + decl.remove(); +}; diff --git a/lib/hide-visually.js b/lib/hide-visually.js new file mode 100644 index 0000000..f9aadff --- /dev/null +++ b/lib/hide-visually.js @@ -0,0 +1,42 @@ +/** + * Hide Visually + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + parentDecl.append({ + prop: 'border', + value: 0, + source: decl.source + }, { + prop: 'clip', + value: 'rect(0 0 0 0)', + source: decl.source + }, { + prop: 'height', + value: '1px', + source: decl.source + }, { + prop: 'margin', + value: '-1px', + source: decl.source + }, { + prop: 'overflow', + value: 'hidden', + source: decl.source + }, { + prop: 'padding', + value: 0, + source: decl.source + }, { + prop: 'position', + value: 'absolute', + source: decl.source + }, { + prop: 'width', + value: '1px', + source: decl.source + }); + + decl.remove(); +}; diff --git a/lib/horizontal-rule.js b/lib/horizontal-rule.js new file mode 100644 index 0000000..cc1a7e5 --- /dev/null +++ b/lib/horizontal-rule.js @@ -0,0 +1,37 @@ +/** + * Horizontal Rule + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + var color = '#cecece'; + var verticalMargin = '3em'; + var height = '1px'; + + if (args[1]) { + color = args[1]; + } + if (args[2]) { + verticalMargin = args[2]; + } + + parentDecl.append({ + prop: 'height', + value: height, + source: decl.source + }, { + prop: 'border', + value: 0, + source: decl.source + }, { + prop: 'border-top', + value: '1px solid ' + color, + source: decl.source + }, { + prop: 'margin', + value: verticalMargin + ' 0', + source: decl.source + }); + + decl.remove(); +}; diff --git a/lib/hover.js b/lib/hover.js new file mode 100644 index 0000000..2c26fb9 --- /dev/null +++ b/lib/hover.js @@ -0,0 +1,24 @@ +/** + * Hover + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent, + ruleSelectors = parentDecl.selectors, + newRule; + + ruleSelectors = ruleSelectors.map(function (ruleSelector) { + return '.no-hover ' + ruleSelector; + }).join(',\n'); + + newRule = parentDecl.cloneAfter({ + selector: ruleSelectors + }).removeAll(); + + newRule.append(decl.nodes); // source + + if (decl.prev() === undefined && decl.next() === undefined) { + parentDecl.remove(); + } else { + decl.remove(); + } +}; diff --git a/lib/no-js.js b/lib/no-js.js new file mode 100644 index 0000000..142c8a6 --- /dev/null +++ b/lib/no-js.js @@ -0,0 +1,24 @@ +/** + * No JS + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent, + ruleSelectors = parentDecl.selectors, + newRule; + + ruleSelectors = ruleSelectors.map(function (ruleSelector) { + return '.no-js ' + ruleSelector; + }).join(',\n'); + + newRule = parentDecl.cloneAfter({ + selector: ruleSelectors + }).removeAll(); + + newRule.append(decl.nodes); // source + + if (decl.prev() === undefined && decl.next() === undefined) { + parentDecl.remove(); + } else { + decl.remove(); + } +}; diff --git a/lib/reset-list.js b/lib/reset-list.js new file mode 100644 index 0000000..38cbee0 --- /dev/null +++ b/lib/reset-list.js @@ -0,0 +1,40 @@ +/** + * Reset List + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + var newRule; + var ruleSelectors = parentDecl.selectors; + + ruleSelectors = ruleSelectors.map(function (ruleSelector) { + return ruleSelector + ' li'; + }).join(',\n'); + + // Insert the :after rule before the original rule + newRule = parentDecl.cloneAfter({ + selector: ruleSelectors + }).removeAll(); + + newRule.append({ + prop: 'list-style', + value: 'none', + source: decl.source + }); + + parentDecl.append({ + prop: 'margin-top', + value: 0, + source: decl.source + },{ + prop: 'margin-bottom', + value: 0, + source: decl.source + },{ + prop: 'padding-left', + value: 0, + source: decl.source + }); + + decl.remove(); +}; diff --git a/lib/text-hide.js b/lib/text-hide.js new file mode 100644 index 0000000..0879bfa --- /dev/null +++ b/lib/text-hide.js @@ -0,0 +1,30 @@ +/** + * Text Hide + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + parentDecl.append({ + prop: 'font', + value: '0/0 a', + source: decl.source + }, { + prop: 'color', + value: 'transparent', + source: decl.source + }, { + prop: 'text-shadow', + value: 'none', + source: decl.source + }, { + prop: 'background-color', + value: 'transparent', + source: decl.source + }, { + prop: 'border', + value: 0, + source: decl.source + }); + + decl.remove(); +}; diff --git a/lib/triangle.js b/lib/triangle.js new file mode 100644 index 0000000..05507e0 --- /dev/null +++ b/lib/triangle.js @@ -0,0 +1,126 @@ +/** + * triangle + * @param {object} decl postcss declaration + * @param {array} args parameters + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + var color = '#000'; + var size = '20px'; + + if (args[1]) { + size = args[1]; + } + if (args[2]) { + color = args[2]; + } + + if (args[3]) { + switch (args[3]) { + case 'down': + border = [true, 't', false, 't']; + break; + case 'up': + border = [false, 't', true, 't']; + break; + case 'left': + border = ['t', true, 't', false]; + break; + case 'right': + border = ['t', false, 't', true]; + break; + case 'up-right': + border = [true, false, false, 't']; + break; + case 'up-left': + border = [true, 't', false, false]; + break; + case 'down-right': + border = [false, false, true, 't']; + break; + case 'down-left': + border = [false, 't', true, false]; + break; + default: + break; + } + } + + parentDecl.append({ + prop: 'height', + value: 0, + source: decl.source + }, { + prop: 'width', + value: 0, + source: decl.source + }); + + if (border[0] === true) { // top + parentDecl.append({ + prop: 'border-top', + value: size + ' solid ' + color, + source: decl.source + }); + } + + if (border[1] === true) { // right + parentDecl.append({ + prop: 'border-right', + value: size + ' solid ' + color, + source: decl.source + }); + } + + if (border[2] === true) { // bottom + parentDecl.append({ + prop: 'border-bottom', + value: size + ' solid ' + color, + source: decl.source + }); + } + + if (border[3] === true) { // left + parentDecl.append({ + prop: 'border-left', + value: size + ' solid ' + color, + source: decl.source + }); + } + + // transparent + if (border[0] === 't') { // top + parentDecl.append({ + prop: 'border-top', + value: size + ' solid transparent', + source: decl.source + }); + } + + if (border[1] === 't') { // right + parentDecl.append({ + prop: 'border-right', + value: size + ' solid transparent', + source: decl.source + }); + } + + if (border[2] === 't') { // bottom + parentDecl.append({ + prop: 'border-bottom', + value: size + ' solid transparent', + source: decl.source + }); + } + + if (border[3] === 't') { // left + parentDecl.append({ + prop: 'border-left', + value: size + ' solid transparent', + source: decl.source + }); + } + + decl.remove(); +}; diff --git a/lib/truncate-multiline.js b/lib/truncate-multiline.js new file mode 100644 index 0000000..f48f719 --- /dev/null +++ b/lib/truncate-multiline.js @@ -0,0 +1,56 @@ +/** + * Truncate Multiline + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + var lineHeight = 1; + var textOverflow = 'ellipsis'; + var lines = args[1].trim(); + + if (args[2]) { + lineHeight = args[2].trim(); + } + + if (args[3]) { + textOverflow = args[3]; + } + + var height = Math.round(lineHeight * lines * 100) / 100; + + parentDecl.append({ + prop: 'display', + value: 'block', + source: decl.source + }, { + prop: 'display', + value: '-webkit-box', + source: decl.source + }, { + prop: 'height', + value: height + 'em', + source: decl.source + }, { + prop: 'line-height', + value: lineHeight, + source: decl.source + }, { + prop: '-webkit-line-clamp', + value: lines, + source: decl.source + }, { + prop: '-webkit-box-orient', + value: 'vertical', + source: decl.source + }, { + prop: 'overflow', + value: 'hidden', + source: decl.source + }, { + prop: 'text-overflow', + value: textOverflow, + source: decl.source + }); + + decl.remove(); +}; diff --git a/lib/truncate.js b/lib/truncate.js new file mode 100644 index 0000000..9d6016d --- /dev/null +++ b/lib/truncate.js @@ -0,0 +1,29 @@ +/** + * Truncate + */ +module.exports = function (decl, args) { + var parentDecl = decl.parent; + + var textOverflow; + if (args.lenth > 1) { + textOverflow = args[1]; + } else { + textOverflow = 'ellipsis'; + } + + parentDecl.append({ + prop: 'white-space', + value: 'nowrap', + source: decl.source + }, { + prop: 'overflow', + value: 'hidden', + source: decl.source + }, { + prop: 'text-overflow', + value: textOverflow, + source: decl.source + }); + + decl.remove(); +}; diff --git a/media/logo.svg b/media/logo.svg new file mode 100644 index 0000000..a5ec1dd --- /dev/null +++ b/media/logo.svg @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..c4123f9 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "postcss-utilities", + "version": "0.1.0", + "description": "PostCSS plugin a collection of mixins, shortcuts, helpers and tools for yout CSS", + "keywords": [ + "postcss", + "css", + "postcss-plugin", + "utility", + "library", + "collection", + "pack", + "helpers", + "mixins", + "shortcuts", + "hacks" + ], + "author": "ismamz ", + "license": "MIT", + "repository": "ismamz/postcss-utilities", + "bugs": { + "url": "https://github.com/ismamz/postcss-utilities/issues" + }, + "homepage": "https://github.com/ismamz/postcss-utilities", + "dependencies": { + "postcss": "^5.0.16", + "postcss-value-parser": "^3.3.0" + }, + "devDependencies": { + "ava": "^0.14.0", + "eslint": "^2.1.0", + "eslint-config-postcss": "^2.0.0", + "fs": "0.0.2" + }, + "scripts": { + "test": "ava && eslint **/*.js" + }, + "eslintConfig": { + "extends": "eslint-config-postcss/es5" + } +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..2261cbb --- /dev/null +++ b/test.js @@ -0,0 +1,58 @@ +import postcss from 'postcss'; +import test from 'ava'; +import fs from 'fs'; + +import plugin from './'; + +function run(t, input, output, opts = { }) { + return postcss([ plugin(opts) ]).process(input) + .then( result => { + fs.writeFileSync('test/out.css', result.css); + t.deepEqual(result.css, output); + t.deepEqual(result.warnings().length, 0); + }); +} + +test('truncate multiline', t => { + return run(t, 'a{ @util truncate (3, 1.5); }', 'a{ display: block; display: -webkit-box; height: 4.5em; line-height: 1.5; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; }', { }); +}); + +test('truncate multiline 2', t => { + return run(t, 'a{ @util truncate(3, 1.5); }', 'a{ display: block; display: -webkit-box; height: 4.5em; line-height: 1.5; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; }', { }); +}); + +test('truncate multiline 3', t => { + return run(t, 'a{ @util truncate(3 1.5); }', 'a{ display: block; display: -webkit-box; height: 4.5em; line-height: 1.5; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; }', { }); +}); + +test('truncate', t => { + return run(t, 'a{ @util truncate; }', 'a{ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }', { }); +}); + +test('reset list', t => { + return run(t, 'ul{ @util reset-list; }', 'ul{ margin-top: 0; margin-bottom: 0; padding-left: 0; }\nul li{ list-style: none; }', { }); +}); + +test('hide visually', t => { + return run(t, 'a{ @util hide-visually; }', 'a{ border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }', { }); +}); + +test('clearfix', t => { + return run(t, 'a{ @util clearfix; }', 'a:after {\n content: \'\';\n display: block;\n clear: both\n}', { }); +}); + +test('text hide', t => { + return run(t, 'a{ background: #000; color: #fff; @util text-hide; }', 'a{ background: #000; color: #fff; font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; }', { }); +}); + +test('triangle', t => { + var input = fs.readFileSync('test/triangle.css', 'utf8'); + var output = fs.readFileSync('test/triangle.expect.css', 'utf8'); + return run(t, input, output, { }); +}); + +test('all', t => { + var input = fs.readFileSync('test/test.css', 'utf8'); + var output = fs.readFileSync('test/test.expect.css', 'utf8'); + return run(t, input, output, { }); +}); diff --git a/test/index.html b/test/index.html new file mode 100644 index 0000000..8a143eb --- /dev/null +++ b/test/index.html @@ -0,0 +1,88 @@ + + + + + PostCSS Utility Library Test + + + + + +
+

PostCSS Utility Library Test

+ +

truncate

+ +

one line - @util truncate;

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit ratione natus, eveniet nihil culpa pariatur dolor consectetur, aperiam laboriosam quam nesciunt beatae voluptate quo odio! Cumque aspernatur nulla consectetur iste.

+ +

multiline - @util truncate 3 1.5;

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cumque consectetur, molestiae nostrum modi voluptas aperiam adipisci dolore eum nesciunt dolores ipsum suscipit beatae, eos vitae qui sapiente deserunt labore minus molestias ut at delectus est quas officiis. Vero magni odit facilis velit, accusantium minima error aut iure. Officiis, commodi, doloribus.

+ +
+ +

hr

+ +

default - @util hr;

+
+ +

custom - @util hr red 1em;

+
+ +
+ +

hide-text

+ +
+ Alternative text + Lorem ipsum dolor sit amet. +
+ +
+ +

triangle

+ +

@util triangle 12px gray down;

+ +
+
+
+
+
+
+
+
+ +
+ +

reset-list

+ +
    +
  • Lorem ipsum dolor sit.
  • +
  • Illo ex porro molestiae?
  • +
  • Earum impedit cum veniam!
  • +
  • Ut tempore, corrupti dolore?
  • +
  • Ipsa, officia totam mollitia.
  • +
+ +
+ +

aspect-ratio

+ +
+
+ 16:9 +
+
+ +
+ 4:3 +
+ +
+
+ + + diff --git a/test/out.css b/test/out.css new file mode 100644 index 0000000..6c7ad67 --- /dev/null +++ b/test/out.css @@ -0,0 +1,158 @@ +body { + margin: 0; + padding: 0; + font-family: sans-serif; +} + +.container { + max-width: 990px; + margin: 0 auto; + padding-left: 15px; + padding-right: 15px; +} + +/* Truncate + ========================================================================== */ +.truncate { + width: 500px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.multiline { + width: 500px; + font-size: 1.2em; + display: block; + display: -webkit-box; + height: 4.5em; + line-height: 1.5; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Hide Visually + ========================================================================== */ +a { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +/* Clear Fix + ========================================================================== */ +.cfx:after { + content: ''; + display: block; + clear: both; +} + +.cfx:after { + content: ''; + display: block; + clear: both; +} + +.cfx { + color: #000; +} + +/* Text Hide + ========================================================================== */ +.text-hide { + background: #000; + color: #fff; + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +/* Horizontal Rule + ========================================================================== */ +hr { + height: 1px; + border: 0; + border-top: 1px solid #cecece; + margin: 3em 0; +} + +.custom-hr { + height: 1px; + border: 0; + border-top: 1px solid red; + margin: 1em 0; +} + +/* Circle + ========================================================================== */ +.circle { + border-radius: 50%; + width: 200px; + height: 200px; + background-color: red; +} + +/* Reset List + ========================================================================== */ +ul { + color: #000; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; +} +ul li { + list-style: none; +} + +/* Media Hover + ========================================================================== */ +.hover { + background-color: #f3f3f3; + color: #000 +} +.no-hover .hover { + background-color: #fff; +} + +/* No JS + ========================================================================== */ +.box { + background-color: #f3f3f3; + color: #000 +} +.no-js .box { + background-color: #fff; +} + +/* Aspect Ratio + ========================================================================== */ +.box-16-9 { + background-color: #ccc; + margin-bottom: 20px; + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; + padding-bottom: 56.25%; +} + +.box-4-3 { + background-color: #ccc; + margin-bottom: 20px; + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; + padding-bottom: 75%; +} diff --git a/test/test.css b/test/test.css new file mode 100644 index 0000000..83a2683 --- /dev/null +++ b/test/test.css @@ -0,0 +1,109 @@ +body { + margin: 0; + padding: 0; + font-family: sans-serif; +} + +.container { + max-width: 990px; + margin: 0 auto; + padding-left: 15px; + padding-right: 15px; +} + +/* Truncate + ========================================================================== */ +.truncate { + @util truncate; + width: 500px; +} + +.multiline { + width: 500px; + font-size: 1.2em; + @util truncate(3, 1.5); +} + +/* Hide Visually + ========================================================================== */ +a { + @util hide-visually; +} + +/* Clear Fix + ========================================================================== */ +.cfx { + @util clearfix; +} + +.cfx { + color: #000; + @util clearfix; +} + +/* Text Hide + ========================================================================== */ +.text-hide { + background: #000; + @util text-hide; + color: #fff; +} + +/* Horizontal Rule + ========================================================================== */ +hr { + @util hr; +} + +.custom-hr { + @util hr(red, 1em); +} + +/* Circle + ========================================================================== */ +.circle { + @util circle(200px, red); +} + +/* Reset List + ========================================================================== */ +ul { + color: #000; + @util reset-list; +} + +/* Media Hover + ========================================================================== */ +.hover { + background-color: #f3f3f3; + color: #000; + + @util hover { + background-color: #fff; + } +} + +/* No JS + ========================================================================== */ +.box { + background-color: #f3f3f3; + color: #000; + + @util no-js { + background-color: #fff; + } +} + +/* Aspect Ratio + ========================================================================== */ +.box-16-9 { + background-color: #ccc; + margin-bottom: 20px; + @util aspect-ratio(16:9); +} + +.box-4-3 { + background-color: #ccc; + margin-bottom: 20px; + @util aspect-ratio(4:3); +} diff --git a/test/test.expect.css b/test/test.expect.css new file mode 100644 index 0000000..6c7ad67 --- /dev/null +++ b/test/test.expect.css @@ -0,0 +1,158 @@ +body { + margin: 0; + padding: 0; + font-family: sans-serif; +} + +.container { + max-width: 990px; + margin: 0 auto; + padding-left: 15px; + padding-right: 15px; +} + +/* Truncate + ========================================================================== */ +.truncate { + width: 500px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.multiline { + width: 500px; + font-size: 1.2em; + display: block; + display: -webkit-box; + height: 4.5em; + line-height: 1.5; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Hide Visually + ========================================================================== */ +a { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +/* Clear Fix + ========================================================================== */ +.cfx:after { + content: ''; + display: block; + clear: both; +} + +.cfx:after { + content: ''; + display: block; + clear: both; +} + +.cfx { + color: #000; +} + +/* Text Hide + ========================================================================== */ +.text-hide { + background: #000; + color: #fff; + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +/* Horizontal Rule + ========================================================================== */ +hr { + height: 1px; + border: 0; + border-top: 1px solid #cecece; + margin: 3em 0; +} + +.custom-hr { + height: 1px; + border: 0; + border-top: 1px solid red; + margin: 1em 0; +} + +/* Circle + ========================================================================== */ +.circle { + border-radius: 50%; + width: 200px; + height: 200px; + background-color: red; +} + +/* Reset List + ========================================================================== */ +ul { + color: #000; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; +} +ul li { + list-style: none; +} + +/* Media Hover + ========================================================================== */ +.hover { + background-color: #f3f3f3; + color: #000 +} +.no-hover .hover { + background-color: #fff; +} + +/* No JS + ========================================================================== */ +.box { + background-color: #f3f3f3; + color: #000 +} +.no-js .box { + background-color: #fff; +} + +/* Aspect Ratio + ========================================================================== */ +.box-16-9 { + background-color: #ccc; + margin-bottom: 20px; + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; + padding-bottom: 56.25%; +} + +.box-4-3 { + background-color: #ccc; + margin-bottom: 20px; + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; + padding-bottom: 75%; +} diff --git a/test/triangle.css b/test/triangle.css new file mode 100644 index 0000000..e98d0fe --- /dev/null +++ b/test/triangle.css @@ -0,0 +1,41 @@ +/* Triangle + ========================================================================== */ +.triangle-down { + @util triangle(12px, gray, down); + display: inline-block; +} + +.triangle-up { + @util triangle(12px, gray, up); + display: inline-block; +} + +.triangle-left { + @util triangle(12px, gray, left); + display: inline-block; +} + +.triangle-right { + @util triangle(12px, gray, right); + display: inline-block; +} + +.triangle-up-left { + @util triangle(20px, gray, up-left); + display: inline-block; +} + +.triangle-up-right { + @util triangle(20px, gray, up-right); + display: inline-block; +} + +.triangle-down-left { + @util triangle(20px, gray, down-left); + display: inline-block; +} + +.triangle-down-right { + @util triangle(20px, gray, down-right); + display: inline-block; +} diff --git a/test/triangle.expect.css b/test/triangle.expect.css new file mode 100644 index 0000000..3c250bf --- /dev/null +++ b/test/triangle.expect.css @@ -0,0 +1,69 @@ +/* Triangle + ========================================================================== */ +.triangle-down { + display: inline-block; + height: 0; + width: 0; + border-top: 12px solid gray; + border-right: 12px solid transparent; + border-left: 12px solid transparent; +} + +.triangle-up { + display: inline-block; + height: 0; + width: 0; + border-bottom: 12px solid gray; + border-right: 12px solid transparent; + border-left: 12px solid transparent; +} + +.triangle-left { + display: inline-block; + height: 0; + width: 0; + border-right: 12px solid gray; + border-top: 12px solid transparent; + border-bottom: 12px solid transparent; +} + +.triangle-right { + display: inline-block; + height: 0; + width: 0; + border-left: 12px solid gray; + border-top: 12px solid transparent; + border-bottom: 12px solid transparent; +} + +.triangle-up-left { + display: inline-block; + height: 0; + width: 0; + border-top: 20px solid gray; + border-right: 20px solid transparent; +} + +.triangle-up-right { + display: inline-block; + height: 0; + width: 0; + border-top: 20px solid gray; + border-left: 20px solid transparent; +} + +.triangle-down-left { + display: inline-block; + height: 0; + width: 0; + border-bottom: 20px solid gray; + border-right: 20px solid transparent; +} + +.triangle-down-right { + display: inline-block; + height: 0; + width: 0; + border-bottom: 20px solid gray; + border-left: 20px solid transparent; +}