├── .editorconfig ├── .gitignore ├── .jshintrc ├── .travis.yml ├── README.md ├── contributors.md ├── docs.json ├── docs └── stylify-package.json ├── examples ├── dep.styl ├── dep2.styl ├── simple.js ├── simple.styl └── test.styl ├── index.js ├── package.json └── test └── transform_test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .package.json 4 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "camelcase": true, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "freeze": true, 6 | "indent": 2, 7 | "newcap": false, 8 | "quotmark": "single", 9 | "maxdepth": 3, 10 | "maxstatements": 50, 11 | "eqnull": true, 12 | "funcscope": true, 13 | "strict": true, 14 | "undef": true, 15 | "unused": true, 16 | "browser": true, 17 | "node": true, 18 | "mocha": true 19 | } 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 6 # lts (boron) 4 | - 7 # stable 5 | 6 | notifications: 7 | email: 8 | - damon.oehlman@gmail.com -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # stylify 2 | 3 | browserify v2 plugin for [stylus](https://github.com/LearnBoost/stylus). 4 | 5 | 6 | [![NPM](https://nodei.co/npm/stylify.png)](https://nodei.co/npm/stylify/) 7 | 8 | [![Build Status](https://travis-ci.org/DamonOehlman/stylify.svg)](https://travis-ci.org/DamonOehlman/stylify) 9 | [![unstable](https://img.shields.io/badge/stability-unstable-yellowgreen.svg)](https://github.com/dominictarr/stability#unstable) 10 | 11 | ## Example Usage 12 | 13 | Usage is very simple when combined with the 14 | [insert-css](https://github.com/substack/insert-css) (or similar) module. 15 | Consider the following example, which dynamically creates a couple of 16 | div tags, and dynamically assigned styles: 17 | 18 | ```js 19 | var insertCss = require('insert-css'); 20 | var crel = require('crel'); 21 | 22 | // create some dom elements to demo our styles 23 | var elements = ['square', 'rect'].map(function(cls) { 24 | return crel('div', { class: 'box ' + cls }); 25 | }).forEach(document.body.appendChild.bind(document.body)); 26 | 27 | // insert our stylus css into our app 28 | insertCss(require('./simple.styl')); 29 | ``` 30 | 31 | You can see the final statement uses a familar node `require` call to 32 | bring in a stylus stylesheet: 33 | 34 | ```css 35 | sidelength = 40px 36 | boxborder = black 37 | 38 | body 39 | margin 0 40 | padding 0 41 | 42 | .box 43 | border: 1px solid boxborder 44 | margin: 5px 45 | 46 | .square 47 | width: sidelength 48 | height: sidelength 49 | 50 | .rect 51 | width: sidelength * 2 52 | height: sidelength 53 | ``` 54 | 55 | ##### Adding paths for @require 56 | Add your stylify config to your application package.json 57 | add a paths array to your mixins folder etc. Paths can be specified in glob notation. 58 | 59 | ```json 60 | "stylify": { 61 | "paths": [ 62 | "application/stylus/**/" 63 | ] 64 | } 65 | 66 | ``` 67 | 68 | ##### Advanced options 69 | 70 | Options can be [passed](https://github.com/substack/node-browserify#user-content-btransformtr-opts) in the follwing form: 71 | 72 | ```js 73 | { 74 | set : { setting: value }, 75 | include: [ path, ... ], 76 | import : [ path, ... ], 77 | define : { key: value }, 78 | use : [ module, ... ] 79 | } 80 | ``` 81 | 82 | where each key corresponds to a stylus method [described here](http://learnboost.github.io/stylus/docs/js.html). 83 | 84 | Here is an example using the javascript api: 85 | 86 | ```js 87 | 88 | var nib = require 'nib'; 89 | var browserify = require 'browserify'; 90 | 91 | // create a browserify bundle 92 | var bundle = browserify({ ... }); 93 | 94 | // register the stylify tranforms with options 95 | bundle.transform('stylify', { 96 | use: [ nib() ], 97 | set: { compress: true } 98 | }); 99 | ``` 100 | 101 | ## License(s) 102 | 103 | ### MIT 104 | 105 | Copyright (c) 2014-2015 Damon Oehlman and contributors 106 | 107 | Permission is hereby granted, free of charge, to any person obtaining 108 | a copy of this software and associated documentation files (the 109 | 'Software'), to deal in the Software without restriction, including 110 | without limitation the rights to use, copy, modify, merge, publish, 111 | distribute, sublicense, and/or sell copies of the Software, and to 112 | permit persons to whom the Software is furnished to do so, subject to 113 | the following conditions: 114 | 115 | The above copyright notice and this permission notice shall be 116 | included in all copies or substantial portions of the Software. 117 | 118 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 119 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 120 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 121 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 122 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 123 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 124 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 125 | -------------------------------------------------------------------------------- /contributors.md: -------------------------------------------------------------------------------- 1 | ###### Contributors 2 | [Damon Oehlman](https://github.com/DamonOehlman) 3 | 30 Commits / 320++ / 145-- 4 | 73.17% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

5 | [Felix](https://github.com/felixhageloh) 6 | 8 Commits / 264++ / 111-- 7 | 19.51% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

8 | [undefined](https://github.com/mikeybox) 9 | 1 Commits / 53++ / 5-- 10 | 02.44% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

11 | [contra](https://github.com/contra) 12 | 1 Commits / 23++ / 15-- 13 | 02.44% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

14 | [Nikita Litvin](https://github.com/deltaidea) 15 | 1 Commits / 5++ / 2-- 16 | 02.44% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

17 | ###### [Generated](https://github.com/jakeleboeuf/contributor) on Thu Mar 26 2015 09:20:17 GMT+1100 (AEDT) -------------------------------------------------------------------------------- /docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "badges": { 3 | "nodeico": true, 4 | "stability": "unstable" 5 | }, 6 | 7 | "license": true 8 | } 9 | -------------------------------------------------------------------------------- /docs/stylify-package.json: -------------------------------------------------------------------------------- 1 | "stylify": { 2 | "paths": [ 3 | "application/stylus/**/" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /examples/dep.styl: -------------------------------------------------------------------------------- 1 | @require 'dep2.styl' -------------------------------------------------------------------------------- /examples/dep2.styl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonOehlman/stylify/25eefa5cbac80fede66f966e0bd1316e2e63dbfb/examples/dep2.styl -------------------------------------------------------------------------------- /examples/simple.js: -------------------------------------------------------------------------------- 1 | var insertCss = require('insert-css'); 2 | var crel = require('crel'); 3 | 4 | // create some dom elements to demo our styles 5 | var elements = ['square', 'rect'].map(function(cls) { 6 | return crel('div', { class: 'box ' + cls }); 7 | }).forEach(document.body.appendChild.bind(document.body)); 8 | 9 | // insert our stylus css into our app 10 | insertCss(require('./simple.styl')); -------------------------------------------------------------------------------- /examples/simple.styl: -------------------------------------------------------------------------------- 1 | sidelength = 40px 2 | boxborder = black 3 | 4 | body 5 | margin 0 6 | padding 0 7 | 8 | .box 9 | border: 1px solid boxborder 10 | margin: 5px 11 | 12 | .square 13 | width: sidelength 14 | height: sidelength 15 | 16 | .rect 17 | width: sidelength * 2 18 | height: sidelength -------------------------------------------------------------------------------- /examples/test.styl: -------------------------------------------------------------------------------- 1 | @require 'dep.styl' 2 | 3 | body 4 | color: rgba(#fff, 0.5) 5 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | 'use strict'; 3 | 4 | var stylus = require('stylus'), 5 | through = require('through2'), 6 | glob = require('glob'), 7 | resolve = require('resolve'), 8 | flatten = require('lodash.flatten'), 9 | uniq = require('lodash.uniq'), 10 | merge = require('lodash.merge'); 11 | 12 | var defaultOptions = { 13 | set: { 14 | paths: [] 15 | }, 16 | include: [], 17 | import: [], 18 | define: {}, 19 | use: [] 20 | }; 21 | 22 | var defaultSourceMapSettings = { 23 | inline: true, 24 | comment: true 25 | }; 26 | 27 | // TODO: allow all options 28 | function getPackageOptions() { 29 | var pkg; 30 | var options = {}; 31 | 32 | try { 33 | pkg = require(process.cwd() + '/package.json'); 34 | } catch (e) {} 35 | 36 | if (!pkg || !pkg.stylify) { 37 | return options; 38 | } 39 | 40 | if (pkg.stylify.use) { 41 | options.use = pkg.stylify.use; 42 | } 43 | if (pkg.stylify.paths) { 44 | options.set = { 45 | paths: pkg.stylify.paths 46 | }; 47 | } 48 | return options; 49 | } 50 | 51 | function parsePaths(paths) { 52 | paths = Array.isArray(paths) ? paths : []; 53 | return uniq(flatten(paths.map(function(path) { 54 | return glob.sync(path); 55 | }))); 56 | } 57 | 58 | function resolveUses(uses) { 59 | if (!Array.isArray(uses)) { 60 | uses = [uses]; 61 | } 62 | 63 | return uses.map(function(mod) { 64 | if (typeof mod === 'string') { 65 | mod = require(resolve.sync(mod, { 66 | basedir: process.cwd() 67 | })); 68 | } 69 | return mod; 70 | }); 71 | } 72 | 73 | function applyOptions(stylus, options) { 74 | ['set', 'include', 'import', 'define', 'use'].forEach(function(method) { 75 | var option = options[method]; 76 | 77 | if (Array.isArray(option)) { 78 | for (var i = 0; i < option.length; i++) 79 | stylus[method](option[i]); 80 | } else { 81 | for (var prop in option) 82 | stylus[method](prop, option[prop]); 83 | } 84 | }); 85 | } 86 | 87 | function compile(file, data, options) { 88 | var style = stylus(data); 89 | applyOptions(style, options); 90 | 91 | var sourceMapSettings = style.get('sourcemap'); 92 | 93 | // always use inline source maps if enabled 94 | if (typeof sourceMapSettings === 'object') { 95 | sourceMapSettings = merge(sourceMapSettings, defaultSourceMapSettings); 96 | } 97 | if (sourceMapSettings === true) { 98 | sourceMapSettings = defaultSourceMapSettings; 99 | } 100 | 101 | style.set('sourcemap', sourceMapSettings); 102 | 103 | // enable compression unless explicitly disabled 104 | style.set('compress', style.get('compress') !== false); 105 | style.set('filename', file); 106 | var compiled = style.render().trim(); 107 | return { 108 | css: 'module.exports = ' + JSON.stringify(compiled) + ';', 109 | deps: style.deps() 110 | }; 111 | } 112 | 113 | module.exports = function (file, options) { 114 | if (!/\.styl$/.test(file)) return through(); 115 | 116 | var data = ''; 117 | var packageOptions = merge( 118 | {}, 119 | defaultOptions, 120 | getPackageOptions() 121 | ); 122 | 123 | options = merge(packageOptions, options || {}); 124 | options.use = resolveUses(options.use); 125 | options.set.paths = parsePaths(options.set.paths); 126 | 127 | function write(buf, enc, cb) { 128 | data += buf.toString(); 129 | cb(); 130 | } 131 | 132 | function end(cb) { 133 | var out; 134 | try { 135 | out = compile(file, data, options); 136 | } catch (err) { 137 | return cb(err); 138 | } 139 | out.deps.forEach(function(dep){ 140 | this.emit('file', dep); 141 | }, this); 142 | this.push(out.css); 143 | cb(); 144 | } 145 | 146 | return through(write, end); 147 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stylify", 3 | "description": "browserify plugin for stylus", 4 | "version": "1.4.0", 5 | "dependencies": { 6 | "glob": "^7.1.1", 7 | "lodash.flatten": "^4.4.0", 8 | "lodash.merge": "^4.6.0", 9 | "lodash.uniq": "^4.5.0", 10 | "resolve": "^1.1.5", 11 | "stylus": "0.54.5", 12 | "through2": "^2.0.0" 13 | }, 14 | "devDependencies": { 15 | "autoprefixer": "^6.7.4", 16 | "concat-stream": "^1.4.7", 17 | "crel": "^3.0.0", 18 | "insert-css": "^2.0.0", 19 | "nib": "1.1.2", 20 | "tap": "^10.2.0" 21 | }, 22 | "scripts": { 23 | "start": "beefy examples/simple.js -- -t ./", 24 | "test": "tap test/*.js" 25 | }, 26 | "main": "index.js", 27 | "keywords": [ 28 | "stylus", 29 | "css", 30 | "browserify", 31 | "browserify-transform" 32 | ], 33 | "license": "MIT", 34 | "directories": { 35 | "doc": "docs", 36 | "example": "examples" 37 | }, 38 | "repository": { 39 | "type": "git", 40 | "url": "https://github.com/DamonOehlman/stylify.git" 41 | }, 42 | "bugs": { 43 | "url": "https://github.com/DamonOehlman/stylify/issues" 44 | }, 45 | "homepage": "https://github.com/DamonOehlman/stylify", 46 | "author": "Damon Oehlman ", 47 | "contributors": [ 48 | { 49 | "url": "https://github.com/mikeybox", 50 | "contributions": 1, 51 | "additions": 53, 52 | "deletions": 5 53 | }, 54 | { 55 | "name": "contra", 56 | "email": "contra@wearefractal.com", 57 | "url": "https://github.com/contra", 58 | "contributions": 1, 59 | "additions": 23, 60 | "deletions": 15, 61 | "hireable": false 62 | }, 63 | { 64 | "name": "Damon Oehlman", 65 | "email": "damon.oehlman@gmail.com", 66 | "url": "https://github.com/DamonOehlman", 67 | "contributions": 30, 68 | "additions": 320, 69 | "deletions": 145, 70 | "hireable": false 71 | }, 72 | { 73 | "name": "Nikita Litvin", 74 | "email": "deltaidea@derpy.ru", 75 | "url": "https://github.com/deltaidea", 76 | "contributions": 1, 77 | "additions": 5, 78 | "deletions": 2, 79 | "hireable": true 80 | }, 81 | { 82 | "name": "Felix", 83 | "email": "", 84 | "url": "https://github.com/felixhageloh", 85 | "contributions": 8, 86 | "additions": 264, 87 | "deletions": 111, 88 | "hireable": false 89 | } 90 | ] 91 | } -------------------------------------------------------------------------------- /test/transform_test.js: -------------------------------------------------------------------------------- 1 | var test = require("tap").test 2 | , fs = require('fs') 3 | , path = require('path') 4 | , concat = require('concat-stream') 5 | , nib = require('nib') 6 | , stylify = require('..'); 7 | 8 | 9 | function transformExampleFile(fileName, options, runTests) { 10 | var data = ''; 11 | 12 | var file = path.join(__dirname, '../examples', fileName); 13 | fs.createReadStream(file) 14 | .pipe(stylify(file, options)) 15 | .pipe(concat({encoding: 'string'}, runTests)); 16 | } 17 | 18 | test('stylify transforms to a css string wrapped in a module', function (t) { 19 | t.plan(2); 20 | 21 | transformExampleFile("test.styl", null, function (transformed) { 22 | t.equal( 23 | transformed, 24 | "module.exports = \"body{color:rgba(255,255,255,0.5)}\";" 25 | ); 26 | 27 | t.notOk(/sourceMappingURL/.test(transformed), "source map is not included"); 28 | }); 29 | }); 30 | 31 | test("it doesn't compress the css if compress is set to false", function (t) { 32 | t.plan(1); 33 | 34 | var options = { 35 | set: { compress: false } 36 | }; 37 | 38 | transformExampleFile("test.styl", options, function (transformed) { 39 | t.equal( 40 | transformed, 41 | "module.exports = \"body {\\n color: rgba(255,255,255,0.5);\\n}\";" 42 | ); 43 | }); 44 | }); 45 | 46 | test("it includes inline source maps if enabled", function (t) { 47 | t.plan(1); 48 | 49 | var options = { 50 | set: { sourcemap: { comment: false } } 51 | }; 52 | 53 | transformExampleFile("test.styl", options, function (transformed) { 54 | t.ok(/sourceMappingURL/.test(transformed), "source map is included"); 55 | }); 56 | }); 57 | 58 | test("it plays nicely with nib", function (t) { 59 | t.plan(1); 60 | 61 | var options = { 62 | use: [ 63 | nib() 64 | ], 65 | set: { 66 | compress: true, 67 | sourcemap: false 68 | } 69 | }; 70 | 71 | transformExampleFile("test.styl", options, function (transformed) { 72 | t.equal( 73 | transformed, 74 | "module.exports = \"body{color:rgba(255,255,255,0.5)}\";" 75 | ); 76 | }); 77 | }); 78 | --------------------------------------------------------------------------------