├── sass ├── base │ ├── _fonts.scss │ ├── _reset.scss │ └── _variables.scss ├── layout │ └── _grid.scss ├── utils │ ├── mixins │ │ ├── _margin-auto.scss │ │ ├── _align-text.scss │ │ ├── _opacity.scss │ │ ├── _box-model.scss │ │ ├── _hide-text.scss │ │ ├── _breakpoint.scss │ │ ├── _replace-text.scss │ │ ├── _max-breakpoint.scss │ │ ├── _min-breakpoint.scss │ │ ├── _hover-focus.scss │ │ ├── _text-shadow.scss │ │ ├── _betweenbreakpoints.scss │ │ ├── _inline-block.scss │ │ ├── _single-transform.scss │ │ ├── _background-cover.scss │ │ ├── _animations.scss │ │ ├── _backface-visibility.scss │ │ ├── _clearfix.scss │ │ ├── _inner-shadow.scss │ │ ├── _box-shadow.scss │ │ ├── _translate.scss │ │ ├── _placeholder.scss │ │ ├── _retina.scss │ │ ├── _keyframes.scss │ │ ├── _animate-link.scss │ │ ├── _transform.scss │ │ ├── _rem.scss │ │ ├── _linear-gradient.scss │ │ ├── _linear-gradient-angle.scss │ │ ├── _transitions.scss │ │ ├── _triangles.scss │ │ └── _rounded-corners.scss │ ├── _extends.scss │ └── _mixins.scss └── style.scss ├── sassysass.gif ├── sassysass-logo.png ├── .gitignore ├── lib ├── write.js ├── mkdir.js └── commands │ ├── help.js │ ├── show.js │ ├── page.js │ ├── explore.js │ ├── unused.js │ ├── install.js │ ├── mixin.js │ ├── theme.js │ └── module.js ├── tests ├── write-test.js ├── help-test.js └── show-test.js ├── templates └── json │ ├── help.json │ └── strings.json ├── TODO.md ├── .travis.yml ├── LICENSE ├── strings.json ├── gulpfile.js ├── bin └── sassysass ├── package.json ├── CHANGELOG.md ├── README.md └── .eslintrc /sass/base/_fonts.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sassysass.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanburgess/sassysass/HEAD/sassysass.gif -------------------------------------------------------------------------------- /sassysass-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanburgess/sassysass/HEAD/sassysass-logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | ~* 3 | *.bak 4 | *.tmp 5 | .sass-cache 6 | *.log 7 | node_modules/ 8 | npm-debug.log 9 | test-output/ 10 | -------------------------------------------------------------------------------- /sass/layout/_grid.scss: -------------------------------------------------------------------------------- 1 | // File Name: _grid.scss 2 | // Description: layout grid 3 | // Used by: page.scss 4 | // Dependencies: 5 | // ------------------------------------------------------------ -------------------------------------------------------------------------------- /lib/write.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | // create new file 4 | module.exports = function write(path, str, mode) { 5 | fs.writeFileSync(path, str, { mode: mode || 0666 }); 6 | return ' \x1b[36mupdate\x1b[0m : ' + path; 7 | }; 8 | -------------------------------------------------------------------------------- /tests/write-test.js: -------------------------------------------------------------------------------- 1 | // 'use strict'; 2 | // var test = require('tape'); 3 | // var write = require('../lib/write'); 4 | 5 | // test('Test write function', function (t) { 6 | // t.notEqual(write('test', 'test'), undefined, 'Pass - Write function working'); 7 | // t.end(); 8 | // }); 9 | -------------------------------------------------------------------------------- /tests/help-test.js: -------------------------------------------------------------------------------- 1 | //this test causing an error 2 | 3 | // var exec = require('child_process').exec; 4 | // exports.helpReturns = function(test) { 5 | // exec(['sassysass help'], function (error, stdout, stderr) { 6 | // test.notEqual(stdout, ''); 7 | // test.done(); 8 | // }); 9 | // }; -------------------------------------------------------------------------------- /lib/mkdir.js: -------------------------------------------------------------------------------- 1 | const mkdirp = require('mkdirp'); 2 | const path = require('path'); 3 | 4 | // make a directory 5 | module.exports = function mkdir(path, fn) { 6 | mkdirp(path, 0755, function(err) { 7 | if (err) throw err; 8 | console.log(' \033[36mcreate\033[0m : ' + path); 9 | return fn && fn(); 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /sass/utils/mixins/_margin-auto.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Margin auto 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include margin-auto(); 8 | 9 | @mixin margin-auto() { 10 | margin-left:auto; 11 | margin-right:auto; 12 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_align-text.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Align inline and inline-block child elements 4 | // example: @include align(center); 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | @mixin align($direction) { 9 | text-align:$direction; 10 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_opacity.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Opacity 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | @mixin opacity($opacity) { 8 | opacity: $opacity; 9 | $opacity-ie: $opacity * 100; 10 | filter: alpha(opacity=$opacity-ie); //IE8 11 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_box-model.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Box Model 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | @mixin box-sizing($box-model) { 8 | -webkit-box-sizing: $box-model; 9 | -moz-box-sizing: $box-model; 10 | box-sizing: $box-model; 11 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_hide-text.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Hide Text 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include hide-text(); 8 | 9 | @mixin hide-text() { 10 | position: relative; 11 | text-indent: -99999px; 12 | display: inline-block; 13 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_breakpoint.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Media Query Breakpoints 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example @include breakpoint(940) { width:80%; } 8 | 9 | @mixin breakpoint($size) { 10 | @media only screen and (max-width: $size + px) { @content; } 11 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_replace-text.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Replace text 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include replace-text(); 8 | 9 | @mixin replace-text() { 10 | border: 0; 11 | color: transparent; 12 | font: 0/0 a; 13 | text-shadow: none; 14 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_max-breakpoint.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Media Query Breakpoints 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example @include max-breakpoint(640) { width:80%; } 8 | 9 | @mixin max-breakpoint($size) { 10 | @media only screen and (max-width: $size + px) { @content; } 11 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_min-breakpoint.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Media Query Breakpoints 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example @include min-breakpoint(940) { width:80%; } 8 | 9 | @mixin min-breakpoint($size) { 10 | @media only screen and (min-width: $size + px) { @content; } 11 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_hover-focus.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Hover and Focus 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example @include hoverFocus('text-decoration', 'none'); 8 | 9 | @mixin hoverFocus($property, $value) { 10 | &:hover, &:focus { 11 | #{$property}: $value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sass/utils/_extends.scss: -------------------------------------------------------------------------------- 1 | // SassySass ------------------------------------------------------------ 2 | 3 | %marginAuto { 4 | @include margin-auto(); 5 | } 6 | 7 | %clearfix { 8 | @include clearfix(); 9 | } 10 | 11 | %inlineBlock { 12 | @include inline-block(); 13 | } 14 | 15 | %hideText { 16 | @include hide-text(); 17 | } 18 | 19 | %left { 20 | float: left; 21 | } 22 | 23 | %right { 24 | float: right; 25 | } 26 | -------------------------------------------------------------------------------- /sass/utils/mixins/_text-shadow.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Text Shadow 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include single-text-shadow(1px, 2px, 2px, #000); 8 | 9 | @mixin single-text-shadow($hoff: false, $voff: false, $blur: false, $color: false) { 10 | text-shadow: $hoff $voff $blur $color; 11 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_betweenbreakpoints.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Media Query Between Breakpoint - min-width -> max-width 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | @mixin betweenbreakpoints($sizeStart,$sizeEnd) { 8 | @media only screen and (min-width: $sizeStart + 1px) and (max-width:$sizeEnd - 1px) 9 | { @content; } 10 | } -------------------------------------------------------------------------------- /tests/show-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var test = require('tape'); 3 | var show = require('../lib/commands/show'); 4 | 5 | test('Test show function', function (t) { 6 | t.equal(show(), undefined, 'Not a command. Try sassysass show '); 7 | t.equal(show('modules'), undefined, 'Sassy Sass: there is currently 0 modules:'); 8 | //t.equal(show('mixins'), undefined, 'Pass - Show mixins working'); 9 | t.end(); 10 | }); -------------------------------------------------------------------------------- /sass/utils/mixins/_inline-block.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Display inline block cross browser 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include inline-block(); 8 | 9 | @mixin inline-block() { 10 | display: -moz-inline-stack; 11 | display: inline-block; 12 | vertical-align: top; 13 | zoom: 1; 14 | *display: inline; 15 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_single-transform.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Single Transform 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include flat-button($greyBlue, white, 5px 15px); 8 | 9 | @mixin single-transform($deg) { 10 | -ms-transform:rotate($deg); 11 | -webkit-transform:rotate($deg); 12 | transform:rotate($deg); 13 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_background-cover.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Background cover 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include background-cover(); 8 | 9 | @mixin background-cover() { 10 | -webkit-background-size: cover; 11 | -moz-background-size: cover; 12 | -o-background-size: cover; 13 | background-size: cover; 14 | } -------------------------------------------------------------------------------- /templates/json/help.json: -------------------------------------------------------------------------------- 1 | { 2 | "usage": "SassySass ", 3 | "commands":{ 4 | "sassysass install": "Starts a new SassySass project", 5 | "sassysass module": "Creates a new SassySass module", 6 | "sassysass theme": "Creates a new SassySass theme", 7 | "sassysass page": "Creates a new SassySass page", 8 | "sassysass show": "Show current modules, pages, or mixins", 9 | "sassysass unused": "Show unused modules, layout, or themes" 10 | } 11 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_animations.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Animations 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include animation('slide-down 5s 3'); 8 | 9 | @mixin animation($str) { 10 | -webkit-animation: #{$str}; 11 | -moz-animation: #{$str}; 12 | -ms-animation: #{$str}; 13 | -o-animation: #{$str}; 14 | animation: #{$str}; 15 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_backface-visibility.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Backface-visibility 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include backface-visibility("hidden"); 8 | 9 | @mixin backface-visibility($value) { 10 | 11 | -webkit-backface-visibility: $value; 12 | -moz-backface-visibility: $value; 13 | backface-visibility: $value; 14 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_clearfix.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Clearfix after element 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include clearfix(); 8 | 9 | @mixin clearfix() { 10 | & { 11 | *zoom: 1; 12 | } 13 | &:before, 14 | &:after { 15 | content: ""; 16 | display: table; 17 | } 18 | &:after { 19 | clear: both; 20 | } 21 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_inner-shadow.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Inner Shadow 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include inner-shadow(1px, 2px, 2px, #000); 8 | 9 | @mixin inner-shadow($hoff: false, $voff: false, $blur: false, $color: false) { 10 | -webkit-box-shadow: inset $hoff $voff $blur $color; 11 | -moz-box-shadow: inset $hoff $voff $blur $color; 12 | box-shadow: inset $hoff $voff $blur $color; 13 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_box-shadow.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Box Shadow 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include box-shadow(1px, 2px, 2px, 2px, #000); 8 | 9 | @mixin box-shadow($hoff: false, $voff: false, $blur: false, $spread: false, $color: false) { 10 | -webkit-box-shadow: $hoff $voff $blur $spread $color; 11 | -moz-box-shadow: $hoff $voff $blur $spread $color; 12 | box-shadow: $hoff $voff $blur $spread $color; 13 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_translate.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Translate 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include translate(0, "z"); 8 | 9 | @mixin translate($value, $axis) { 10 | -webkit-transform: translate + $axis($value); 11 | -moz-transform: translate + $axis($value); 12 | -ms-transform: translate + $axis($value); 13 | -o-transform: translate + $axis($value); 14 | transform: translate + $axis($value); 15 | } -------------------------------------------------------------------------------- /lib/commands/help.js: -------------------------------------------------------------------------------- 1 | var pkg = require('../../package.json'); 2 | var help = require('../../templates/json/help.json'); 3 | var version = pkg.version; 4 | var commands; 5 | var output = ''; 6 | 7 | output += '\nSassy Sass ' + version + '\n'; 8 | output += '\nUsage: ' + help.usage + '\n'; 9 | output += '\nCommands:\n'; 10 | 11 | commands = help.commands; 12 | module.exports = function help() { 13 | for (var key in commands) { 14 | if (commands.hasOwnProperty(key)) { 15 | output += key + ' = ' + commands[key] + '\n'; 16 | } 17 | } 18 | console.log(output); 19 | }; 20 | -------------------------------------------------------------------------------- /sass/utils/mixins/_placeholder.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Change placeholder text color 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include placeholder-color(#333); 8 | 9 | @mixin placeholder-color($color) { 10 | &.placeholder { 11 | color: $color 12 | } 13 | 14 | &:-moz-placeholder { 15 | color: $color 16 | } 17 | 18 | &::-webkit-input-placeholder { 19 | color: $color 20 | } 21 | 22 | &:-ms-input-placeholder { 23 | color: $color 24 | } 25 | } -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | Feel free to contribute :) 4 | 5 | * Add Scss linting using something like [oddbird/true](https://github.com/oddbird/true) 6 | * Create mixin feature [Issue 10](https://github.com/ryanburgess/sassysass/issues/10) 7 | * 100% test coverage 8 | * New site design for [SassySass.com](http://sassysass.com) [Issue 6](https://github.com/ryanburgess/sassysass/issues/6) 9 | * Create themes and boilerplate modules 10 | * Create way to install new modules, mixins or themes 11 | * Add support for Font Awesome 12 | * Use something like [mdcss](https://github.com/jonathantneal/mdcss-theme-github) to create an automated CSS style guide -------------------------------------------------------------------------------- /sass/utils/mixins/_retina.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Retina Images 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include retina("logo2x.png", 100, 50); 8 | 9 | @mixin retina($image, $width, $height) { 10 | @media (min--moz-device-pixel-ratio: 1.3), 11 | (-o-min-device-pixel-ratio: 2.6/2), 12 | (-webkit-min-device-pixel-ratio: 1.3), 13 | (min-device-pixel-ratio: 1.3), 14 | (min-resolution: 1.3dppx) { 15 | background-image: url("#{$image}"); 16 | background-size: $width + px $height + px; 17 | } 18 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_keyframes.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Keyframes 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include keyframes(slide-down) {0%{ opacity:1; } 90%{ opacity:0; }} 8 | 9 | @mixin keyframes($animation-name) { 10 | @-webkit-keyframes #{$animation-name} { 11 | @content; 12 | } 13 | @-moz-keyframes #{$animation-name} { 14 | @content; 15 | } 16 | @-ms-keyframes #{$animation-name} { 17 | @content; 18 | } 19 | @-o-keyframes #{$animation-name} { 20 | @content; 21 | } 22 | @keyframes #{$animation-name} { 23 | @content; 24 | } 25 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_animate-link.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Animated link that has a fade-in underline 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include animate-link($screenGreen, $gothamMedium, 14); 8 | 9 | @mixin animate-link($color, $font, $fontSize) { 10 | 11 | font-family:$font; 12 | 13 | @include single-transition(border, 0.2s, ease-in-out, 0); 14 | text-decoration:none; 15 | 16 | color: $color; 17 | border-bottom:1px solid transparent; 18 | 19 | @include rem("font-size", $fontSize); 20 | 21 | &:focus, 22 | &:hover { 23 | border-color: $color; 24 | } 25 | } -------------------------------------------------------------------------------- /sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | html { 2 | font-size:62.5%; 3 | } 4 | 5 | body { 6 | margin:0; 7 | padding:0; 8 | width:100%; 9 | @include rem("font-size", $regularSize); 10 | font-family:$helvetica; 11 | line-height:1.3; 12 | } 13 | 14 | ul { 15 | list-style:none; 16 | margin:0; 17 | padding:0; 18 | } 19 | 20 | ul li { 21 | margin:0; 22 | padding:0; 23 | } 24 | 25 | ol { 26 | margin:0; 27 | padding:0; 28 | } 29 | p { 30 | padding:0; 31 | @include rem("margin", 0, 0, 5, 0); 32 | } 33 | 34 | h1, h2, h3, h4, h5, h6 { 35 | padding:0; 36 | @include rem("margin", 0, 0, 10, 0); 37 | font-weight: normal; 38 | } 39 | 40 | fieldset { 41 | border:none; 42 | margin:0; 43 | padding:0; 44 | } 45 | 46 | button { 47 | cursor:pointer; 48 | } 49 | 50 | %clearfix { 51 | @include clearfix(); 52 | } 53 | -------------------------------------------------------------------------------- /sass/utils/mixins/_transform.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Transform 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include transform("origin", 0, 0); 8 | 9 | @mixin transform($type, $values...) { 10 | $n: length($values); 11 | $i: 1; 12 | 13 | $originVal: (); 14 | 15 | @while $i <= $n { 16 | $itemVal: (nth($values, $i)); 17 | @if $type == "rotate" or $type == "rotateY" or $type == "rotateX" { 18 | $originVal: append($originVal, $itemVal + deg); 19 | } @else { 20 | $originVal: append($originVal, $itemVal + px); 21 | } 22 | 23 | $i: $i + 1; 24 | } 25 | -webkit-transform: #{$type}($originVal); 26 | -moz-transform: #{$type}($originVal); 27 | transform: #{$type}($originVal); 28 | } -------------------------------------------------------------------------------- /sass/base/_variables.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | // Layout Breakpoints 3 | // ---------------------------------------------------------------------- 4 | $sassyLarge: 1280; 5 | $sassyMed: 1040; 6 | $sassySmall: 600; 7 | $sassyXSmall: 400; 8 | 9 | // ---------------------------------------------------------------------- 10 | // Font Sizes 11 | // ---------------------------------------------------------------------- 12 | $regularSize: 12; 13 | 14 | // ---------------------------------------------------------------------- 15 | // Font Families 16 | // ---------------------------------------------------------------------- 17 | $helvetica: Helvetica, Arial, sans-serif; 18 | 19 | // ---------------------------------------------------------------------- 20 | // Grid 21 | // ---------------------------------------------------------------------- 22 | $grid-columns: 12; 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '4.1' 5 | - '4.0' 6 | - '0.12' 7 | - '0.11' 8 | - '0.10' 9 | before_script: 10 | - npm install sassysass -g 11 | - npm install gulp-cli -g 12 | - sassysass install 13 | notifications: 14 | slack: 15 | secure: hbl9SQsPgoEYoRHs/LwH++A0XgynoJgO7pkV+fsuOnVew8qNPD0pp3x7Yzs2alPXc5uDxGaCFDCUPsdBIVhJYYCMCLt6XG3JejL3IP0wumgOFe7QPFP9vmVaoRNCW4pK6TTRwq8yVbk9DmUShnMPixxMk9BVQt2b8AJi9E2S3n0RrDOf30MQ0op+hcjJhSHAVeafCRQ9UBrmx6RAaWRaXO1tN+XwLmYm2eqJrdJTL0RSXE0Gczik8acdxVBGLmzjAxmqyXDF2eetTxjXxZMLSEjIwxmjTGtPzxLEVxXx57q2RosGQvpq5QB6t2XpCjGtYXkLhOoTOMigETOcLtHDLCIgRZ6ojR1QjGdlUxDZuYt40ANMUHCDcZjQg5+3qf00M6wc4McU2S/KpG04lXjimt4pc5Qf2E7T7rVGCoyoGR1PG+LTo3avFSPtvbhXcTI5QxJ/4AAB1wXOpjNGaBhnv3d0D7+TabasDdPhUxT5AnKxeWfMx0krtRF1QLUbwcDUIlizFhzFS5E9FNAPXnhU4QOS6/3BhRkRpoxfRYC2Yaz5fn3wb37XB6t0IrkFi71tyk5iqCjXsMsHaDd8SNjlDFfZhUyG5EpOFqBUBkaV6Yuhtq5etIpn7an4VbiK8srnQaYwIfl3xuuhZJM8jrN3wgxYdRfsTgzWM9s79DHBZKM= 16 | -------------------------------------------------------------------------------- /sass/utils/mixins/_rem.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // REM Units with PX fallback 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include rem("margin", 10, 5, 10, 5); 8 | // example: @include rem("font-size", 14); 9 | 10 | @mixin rem($property, $values...) { 11 | $n: length($values); 12 | $i: 1; 13 | 14 | $pxlist: (); 15 | $remlist: (); 16 | 17 | @while $i <= $n { 18 | $itemVal: (nth($values, $i)); 19 | @if $itemVal != "auto"{ 20 | $pxlist: append($pxlist, $itemVal + px); 21 | //$remlist: append($remlist, ($itemVal / 10) + rem); // Use this if you've set HTML font size value to 62.5% 22 | $remlist: append($remlist, ($itemVal / 16) + rem); 23 | } @else { 24 | $pxlist: append($pxlist, auto); 25 | $remlist: append($remlist, auto); 26 | } 27 | 28 | $i: $i + 1; 29 | } 30 | 31 | #{$property}: $pxlist; 32 | #{$property}: $remlist; 33 | } -------------------------------------------------------------------------------- /lib/commands/show.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs-extra'); 2 | var path = require('path'); 3 | var strings = require('../../templates/json/strings.json'); 4 | var dir = path.dirname(); 5 | var ouput = ''; 6 | 7 | module.exports = function show(type) { 8 | var files; 9 | var num = 0; 10 | var correct = true; 11 | if (type === 'pages') { 12 | files = fs.readdirSync(dir + '/sass/'); 13 | }else if(type === 'modules' || type === 'themes' || type === 'layout') { 14 | files = fs.readdirSync(dir + '/sass/' + type); 15 | }else if(type === 'mixins') { 16 | files = fs.readdirSync(dir + '/sass/utils/' + type); 17 | }else { 18 | correct = false; 19 | console.log('\n' + strings.errors.showNotCommand + '\n'); 20 | } 21 | if(correct === true) { 22 | for (var i in files) { 23 | if(files[i].indexOf('.scss') > -1) { 24 | num++; 25 | ouput += files[i] + '\n'; 26 | } 27 | } 28 | console.log('\n' + strings.messages.showThereCurrently + ' ' + num + ' ' + type + ':\n'); 29 | console.log(ouput); 30 | } 31 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /sass/style.scss: -------------------------------------------------------------------------------- 1 | // SassySass ------------------------------------------------------------ 2 | 3 | // ---------------------------------------------------------------------- 4 | // Utils 5 | // ---------------------------------------------------------------------- 6 | @import "utils/mixins"; 7 | @import "utils/extends"; 8 | 9 | // ---------------------------------------------------------------------- 10 | // Base 11 | // ---------------------------------------------------------------------- 12 | @import "base/variables"; 13 | @import "base/reset"; 14 | 15 | // ---------------------------------------------------------------------- 16 | // Layout 17 | // ---------------------------------------------------------------------- 18 | @import "layout/grid"; 19 | 20 | // ---------------------------------------------------------------------- 21 | // Modules 22 | // ---------------------------------------------------------------------- 23 | 24 | // ---------------------------------------------------------------------- 25 | // Themes 26 | // ---------------------------------------------------------------------- 27 | 28 | 29 | -------------------------------------------------------------------------------- /sass/utils/mixins/_linear-gradient.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Linear Gradients 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include linearGradient(#cccccc, #333333); 8 | 9 | @mixin linearGradient($top, $bottom) { 10 | background: #{$top}; /* Old browsers */ 11 | background: -moz-linear-gradient(top, #{$top} 0%, #{$bottom} 100%); /* FF3.6+ */ 12 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #{$top}), color-stop(100%, #{$bottom})); /* Chrome,Safari4+ */ 13 | background: -webkit-linear-gradient(top, #{$top} 0%, #{$bottom} 100%); /* Chrome10+,Safari5.1+ */ 14 | background: -o-linear-gradient(top, #{$top} 0%, #{$bottom} 100%); /* Opera 11.10+ */ 15 | background: -ms-linear-gradient(top, #{$top} 0%, #{$bottom} 100%); /* IE10+ */ 16 | background: linear-gradient(to bottom, #{$top} 0%, #{$bottom} 100%); /* W3C */ 17 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#{$top}', endColorstr='#{$bottom}', GradientType=0 ); /* IE6-9 */ 18 | } -------------------------------------------------------------------------------- /strings.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"SassySass", 3 | "questions": { 4 | "pathToModule": "Path to modules directory?", 5 | "moduleDesc": "What is this module used for?", 6 | "moduleAddToPage": "What pages do you want to add this module to?", 7 | "pathToPage": "Path to page directory?", 8 | "addModules": "Add modules to page?", 9 | "mixinInstall": "What mixin would you like to install?", 10 | "namePage": "What is the name of the page?", 11 | "nameModule": "What is the name of the module?" 12 | }, 13 | "errors": { 14 | "directoryPath": "Directory path might be wrong", 15 | "moduleExists": "Module already exists, please choose another name", 16 | "pageExists": "Page already exists, please choose another name", 17 | "showNotCommand": "Not a command. Try sassysass show ", 18 | "alreadyExists": "already exists" 19 | }, 20 | "messages": { 21 | "showThereCurrently": "Sassy Sass: there is currently", 22 | "pageVersion": "SassySass page v", 23 | "moduleVersion": "SassySass module v", 24 | "wasCreated": ".scss was created" 25 | } 26 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_linear-gradient-angle.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Linear Gradient angle 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include linear-gradient(-10, #cccccc, #333333); 8 | 9 | @mixin linear-gradient($angle, $colorStart, $colorStop) { 10 | background: #{$colorStart}; /* Old browsers */ 11 | background: -moz-linear-gradient($angle, #{$colorStart} 0%, #{$colorStop} 100%); /* FF3.6+ */ 12 | background: -webkit-gradient(linear, left bottom, right top, color-stop(0%,#{$colorStart}), color-stop(100%,#{$colorStop})); /* Chrome,Safari4+ */ 13 | background: -webkit-linear-gradient(45deg, #{$colorStart} 0%,#{$colorStop} 100%); /* Chrome10+,Safari5.1+ */ 14 | background: -o-linear-gradient(45deg, #{$colorStart} 0%,#{$colorStop} 100%); /* Opera 11.10+ */ 15 | background: -ms-linear-gradient(45deg, #{$colorStart} 0%,#{$colorStop} 100%); /* IE10+ */ 16 | background: linear-gradient(45deg, #{$colorStart} 0%,#{$colorStop} 100%); /* W3C */ 17 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#{$colorStart}', endColorstr='#{$colorStop}',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ 18 | } -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const jsonlint = require('gulp-jsonlint'); 3 | const nodeunit = require('gulp-nodeunit'); 4 | const jshintStyle = require('jshint-stylish'); 5 | const eslint = require('gulp-eslint'); 6 | const path = require('path'); 7 | 8 | // ESLint 9 | gulp.task('lint', function () { 10 | return gulp.src(['./bin/*', './lib/commands/*']) 11 | .pipe(eslint()) 12 | .pipe(eslint.format()) 13 | .pipe(eslint.failAfterError()); 14 | }); 15 | 16 | // JSON Lint 17 | gulp.task('jsonlint', function() { 18 | return gulp.src(['./templates/json/*.json', './*.json']) 19 | .pipe(jsonlint()) 20 | .pipe(jsonlint.reporter(jshintStyle)); 21 | }); 22 | 23 | // watch tasks 24 | gulp.task('watch', function() { 25 | gulp.watch(['./*.json', './templates/json/*.json'], ['jsonlint']); 26 | gulp.watch(['bin/*', 'lib/**/*'], ['lint']); 27 | gulp.watch(['./templates/json/*.json', 'package.json'], ['jsonlint']); 28 | }); 29 | 30 | // nodeunit tests 31 | gulp.task('nodeunit', function () { 32 | gulp.src('tests/**/*.js') 33 | .pipe(nodeunit({ 34 | reporter: 'junit', 35 | reporterOptions: { 36 | output: 'test-output' 37 | } 38 | })); 39 | }); 40 | 41 | gulp.task('test', ['lint', 'jsonlint', 'nodeunit']); 42 | gulp.task('default', ['watch']); 43 | -------------------------------------------------------------------------------- /bin/sassysass: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var argument = process.argv[2]; 3 | var argumentSec = process.argv[3]; 4 | 5 | var createPage = require('../lib/commands/page'); 6 | var createModule = require('../lib/commands/module'); 7 | var createTheme = require('../lib/commands/theme'); 8 | var createMixin = require('../lib/commands/mixin'); 9 | var install = require('../lib/commands/install'); 10 | var show = require('../lib/commands/show'); 11 | var unused = require('../lib/commands/unused'); 12 | var help = require('../lib/commands/help'); 13 | var explore = require('../lib/commands/explore'); 14 | 15 | switch (true) { 16 | case (argument === 'install'): 17 | install(); 18 | break; 19 | case (argument === 'page'): 20 | createPage(); 21 | break; 22 | case (argument === 'module'): 23 | createModule(); 24 | break; 25 | case (argument === 'theme'): 26 | createTheme(); 27 | break; 28 | case (argument === 'mixin'): 29 | createMixin(); 30 | break; 31 | case (argument === 'help'): 32 | help(); 33 | break; 34 | case (argument === 'show'): 35 | show(argumentSec); 36 | break; 37 | case (argument === 'unused'): 38 | unused(argumentSec); 39 | break; 40 | case (argument === 'explore'): 41 | explore(); 42 | break; 43 | default: 44 | help(); 45 | break; 46 | } 47 | -------------------------------------------------------------------------------- /sass/utils/mixins/_transitions.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Transitions 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include single-transition(background, 1s, ease-in-out, 0); 8 | 9 | @mixin single-transition($property, $duration, $timing-function, $delay) { 10 | -webkit-transition: $property $duration $timing-function $delay; 11 | -moz-transition: $property $duration $timing-function $delay; 12 | -o-transition: $property $duration $timing-function $delay; 13 | transition: $property $duration $timing-function $delay; 14 | } 15 | 16 | // example: @include double-transition(background, 1s, ease-in-out, 0, opacity, .1s, ease-in-out, 0); 17 | 18 | @mixin double-transition($property1, $duration1, $timing-function1, $delay1, $property2, $duration2, $timing-function2, $delay2) { 19 | -webkit-transition: $property1 $duration1 $timing-function1 $delay1, $property2 $duration2 $timing-function2 $delay2; 20 | -moz-transition: $property1 $duration1 $timing-function1 $delay1, $property2 $duration2 $timing-function2 $delay2; 21 | -o-transition: $property1 $duration1 $timing-function1 $delay1, $property2 $duration2 $timing-function2 $delay2; 22 | transition: $property1 $duration1 $timing-function1 $delay1, $property2 $duration2 $timing-function2 $delay2; 23 | } -------------------------------------------------------------------------------- /templates/json/strings.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"SassySass", 3 | "questions": { 4 | "pathToModule": "Path to modules directory?", 5 | "moduleDesc": "What is this module used for?", 6 | "themeDesc": "What is this theme used for?", 7 | "moduleAddToPage": "What pages do you want to add this module to?", 8 | "themeAddToPage": "What pages do you want to add this theme to?", 9 | "pathToPage": "Path to page directory?", 10 | "pathToTheme": "Path to themes directory?", 11 | "addModules": "Add modules to page?", 12 | "addTheme": "Add theme to page?", 13 | "mixinInstall": "What mixin would you like to install?", 14 | "nameModule": "What is the name of the module?", 15 | "namePage": "What is the name of the page?", 16 | "nameTheme": "What is the name of the theme?" 17 | }, 18 | "errors": { 19 | "directoryPath": "Directory path might be wrong", 20 | "moduleExists": "Module already exists, please choose another name", 21 | "pageExists": "Page already exists, please choose another name", 22 | "themeExists": "Theme already exists, please choose another name", 23 | "showNotCommand": "Not a command. Try sassysass show ", 24 | "alreadyExists": "already exists" 25 | }, 26 | "messages": { 27 | "showThereCurrently": "Sassy Sass: there is currently", 28 | "pageVersion": "SassySass page v", 29 | "moduleVersion": "SassySass module v", 30 | "themeVersion": "SassySass theme v", 31 | "wasCreated": ".scss was created" 32 | } 33 | } -------------------------------------------------------------------------------- /sass/utils/mixins/_triangles.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Arrows / Triangles 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include arrow("left", #cccccc, 10); 8 | 9 | @mixin arrow($direction, $color, $size) { 10 | $pxSize: $size + px; 11 | $remSize: ($size / 10) + rem; 12 | 13 | width: 0; 14 | height: 0; 15 | 16 | @if $direction == "left"{ 17 | border-top: $pxSize solid transparent; 18 | border-right: $pxSize solid $color; 19 | border-bottom: $pxSize solid transparent; 20 | 21 | border-top: $remSize solid transparent; 22 | border-right: $remSize solid $color; 23 | border-bottom: $remSize solid transparent; 24 | }@else if $direction == "right"{ 25 | border-top: $pxSize solid transparent; 26 | border-bottom: $pxSize solid transparent; 27 | border-left: $pxSize solid $color; 28 | 29 | border-top: $remSize solid transparent; 30 | border-bottom: $remSize solid transparent; 31 | border-left: $remSize solid $color; 32 | }@else if $direction == "up"{ 33 | border-left: $pxSize solid transparent; 34 | border-right: $pxSize solid transparent; 35 | border-bottom: $pxSize solid $color; 36 | 37 | border-left: $remSize solid transparent; 38 | border-right: $remSize solid transparent; 39 | border-bottom: $remSize solid $color; 40 | }@else if $direction == "down"{ 41 | border-left: $pxSize solid transparent; 42 | border-right: $pxSize solid transparent; 43 | border-top: $pxSize solid $color; 44 | 45 | border-left: $remSize solid transparent; 46 | border-right: $remSize solid transparent; 47 | border-top: $remSize solid $color; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sassysass", 3 | "version": "1.3.1", 4 | "description": "Sassy Sass is a CSS architecture scaffolding for Sass.", 5 | "main": "bin/sassysass", 6 | "preferGlobal": true, 7 | "bin": { 8 | "sassysass": "./bin/sassysass" 9 | }, 10 | "scripts": { 11 | "test": "gulp test" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/ryanburgess/sassysass.git" 16 | }, 17 | "keywords": [ 18 | "sass", 19 | "scss", 20 | "sassysass", 21 | "boilerplate", 22 | "scaffolding", 23 | "build", 24 | "architecture", 25 | "smacss", 26 | "methodology" 27 | ], 28 | "authors": [ 29 | "Ryan Burgess @burgessdryan", 30 | "Wai Lun Poon @monkeytypewritr", 31 | "Augustus Yuan @augburto" 32 | ], 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/ryanburgess/sassysass/issues" 36 | }, 37 | "engines": { 38 | "node": ">=0.10.0" 39 | }, 40 | "dependencies": { 41 | "async": "^1.5.0", 42 | "fs-extra": "^0.16.5", 43 | "get-date": "^1.0.2", 44 | "install": "^0.1.8", 45 | "mkdirp": "^0.5.1", 46 | "npm": "^2.14.15", 47 | "path": "^0.11.14", 48 | "prepend-file": "^1.3.0", 49 | "prompt": "^0.2.14", 50 | "request": "^2.67.0" 51 | }, 52 | "devDependencies": { 53 | "babel-eslint": "^5.0.0-beta4", 54 | "eslint": "^1.10.3", 55 | "eslint-plugin-babel": "^3.0.0", 56 | "ghooks": "^1.0.1", 57 | "gulp": "^3.9.0", 58 | "gulp-eslint": "^1.1.1", 59 | "gulp-jsonlint": "^1.1.1", 60 | "gulp-nodeunit": "0.0.5", 61 | "https": "^1.0.0", 62 | "jshint": "^2.9.1-rc1", 63 | "jshint-stylish": "^2.1.0", 64 | "tape": "^4.2.2" 65 | }, 66 | "config": { 67 | "ghooks": { 68 | "pre-commit": "gulp lint", 69 | "pre-push": "gulp test", 70 | "post-merge": "npm install", 71 | "post-rewrite": "npm install" 72 | } 73 | }, 74 | "peerDependencies": {}, 75 | "homepage": "https://github.com/ryanburgess/sassysass#readme" 76 | } 77 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Release History 2 | 3 | * 1.3.1: Bug fixes. 4 | * 1.3.0: Add command to create a new theme. 5 | * 1.2.9: Improvements to file structure. 6 | * 1.2.8: Bug fixes. 7 | * 1.2.7: Merge pull request for new mixins. Change page.scss to style.scss. 8 | * 1.2.6: Update dependencies. 9 | * 1.2.5: Use request on commands. 10 | * 1.2.4: [Issue 18](https://github.com/ryanburgess/sassysass/issues/18) Fixed the sassysass module command. 11 | * 1.2.3: Don't ask to delete unused files if 0 are returned. 12 | * 1.2.2: Fixed Retina mixin. 13 | * 1.2.1: Remove old bin commands. 14 | * 1.2.0: Add max-width breakpoint to mixins directory. 15 | * 1.1.9: Prompt user if unused files should be deleted. 16 | * 1.1.8: Add unused command to show unused files (modules, themes, layout) 17 | * 1.1.7: Add show command to show available files (modules, themes, pages, mixins) 18 | * 1.1.6: Use one command passing arguements. Example: sassysass install, sassysass page, sassysass help 19 | * 1.1.5: [Issue 11](https://github.com/ryanburgess/sassysass/issues/11) Option to overwrite module or page. 20 | * 1.1.4: Small fix in the sassysass command. 21 | * 1.1.3: Remove header, footer, red example modules because people were getting confused when they were in the sassysass build. 22 | * 1.1.2: [Issue 12](https://github.com/ryanburgess/sassysass/issues/12) Fix help command to pull help.json. 23 | * 1.1.1: Clean up command files and add Gulp for JSHint. 24 | * 1.1.0: Add help command. 25 | * 1.0.9: [Issue 8](https://github.com/ryanburgess/sassysass/issues/8) Update translate mixin to use a axis variable. 26 | * 1.0.8: [Issue 2](https://github.com/ryanburgess/sassysass/issues/2) add import reference to root SCSS files when creating a new module. 27 | * 1.0.7: Add modules to a page when creating the page SCSS file. 28 | * 1.0.6: add description question for creating a module. 29 | * 1.0.5: [Issue 1](https://github.com/ryanburgess/sassysass/issues/1) - prevent overwriting files. 30 | * 1.0.4: [Pull 4](https://github.com/ryanburgess/sassysass/pull/4) - added some "sass" to the prompts. 31 | * 1.0.3: [Issue 3](https://github.com/ryanburgess/sassysass/issues/3) - add prompts for setting up modules and pages. 32 | * 1.0.2: Add animated terminal gif to demonstrate SassySass in use. 33 | * 1.0.1: Update documentation. 34 | * 1.0.0: Initial release. -------------------------------------------------------------------------------- /sass/utils/mixins/_rounded-corners.scss: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // Rounded Corners 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | // example: @include roundedCorners(10); 8 | 9 | @mixin roundedCorners($size) { 10 | -webkit-border-radius: $size + px; 11 | -moz-border-radius: $size + px; 12 | border-radius: $size + px; 13 | } 14 | 15 | // Rounded Corners Top Only 16 | @mixin roundedTop($size) { 17 | -webkit-border-radius: $size + px $size + px 0 0; 18 | -moz-border-radius: $size + px $size + px 0 0; 19 | border-radius: $size + px $size + px 0 0; 20 | } 21 | 22 | // Rounded Corner Top Left Only 23 | @mixin roundedTopLeft($size) { 24 | -webkit-border-radius: $size + px 0 0 0; 25 | -moz-border-radius: $size + px 0 0 0; 26 | border-radius: $size + px 0 0 0; 27 | } 28 | 29 | // Rounded Corner Top Right Only 30 | @mixin roundedTopRight($size) { 31 | -webkit-border-radius: 0 $size + px 0 0; 32 | -moz-border-radius: 0 $size + px 0 0; 33 | border-radius: 0 $size + px 0 0; 34 | } 35 | 36 | // Rounded Corners Bottom Only 37 | @mixin roundedBottom($size) { 38 | -webkit-border-radius: 0 0 $size + px $size + px; 39 | -moz-border-radius: 0 0 $size + px $size + px; 40 | border-radius: 0 0 $size + px $size + px; 41 | } 42 | 43 | // Rounded Corner Bottom Left Only 44 | @mixin roundedBottomLeft($size) { 45 | -webkit-border-radius: 0 0 0 $size + px; 46 | -moz-border-radius: 0 0 0 $size + px; 47 | border-radius: 0 0 0 $size + px; 48 | } 49 | 50 | // Rounded Corner Bottom Right Only 51 | @mixin roundedBottomRight($size) { 52 | -webkit-border-radius: 0 0 $size + px 0; 53 | -moz-border-radius: 0 0 $size + px 0; 54 | border-radius: 0 0 $size + px 0; 55 | } 56 | 57 | // Rounded Corners Left Only 58 | @mixin roundedLeft($size) { 59 | -webkit-border-radius: 0 0 $size + px $size + px; 60 | -moz-border-radius: 0 0 $size + px $size + px; 61 | border-radius: $size + px 0 0 $size + px; 62 | } 63 | 64 | // Rounded Corners Right Only 65 | @mixin roundedRight($size) { 66 | -webkit-border-radius: 0 $size + px $size + px 0; 67 | -moz-border-radius: 0 $size + px $size + px 0; 68 | border-radius: 0 $size + px $size + px 0; 69 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sassy Sass 2 | [![npm version](https://badge.fury.io/js/sassysass.svg)](http://badge.fury.io/js/sassysass) [![npm](https://img.shields.io/npm/dm/sassysass.svg)](https://github.com/ryanburgess/sassysass) [![Build Status](https://travis-ci.org/ryanburgess/sassysass.svg?branch=master)](https://travis-ci.org/ryanburgess/sassysass) 3 | 4 | ![Sassy Sass Logo](https://raw.github.com/ryanburgess/sassysass/master/sassysass-logo.png) 5 | 6 | Sassy Sass is a scaffolding tool to help you organize your project’s Sass structure. 7 | 8 | With a simple command, add a well-structured architecture for your project's CSS. Based off the [SMACSS](https://smacss.com/) methodology, SassySass creates a simple, maintainable structure for your Sass files. 9 | 10 | ![SassySass in the terminal](https://raw.github.com/ryanburgess/sassysass/master/sassysass.gif) 11 | 12 | ## Install 13 | 14 | ```js 15 | npm install sassysass -g 16 | ``` 17 | ## Use 18 | Run ```sassysass install``` in your project directory. 19 | 20 | To create new individual Sass files run ```sassysass page```. If the name isn't set the file will be named 'page' and if the path isn't set it assumes the directory is 'sass'. 21 | 22 | To create new Sass module run ```sassysass module```. If the name isn't set the file will be named 'module' and if the path isn't set it assumes the directory is 'sass/modules'. 23 | 24 | Sassy Sass Architecture 25 | ---------- 26 | 1. Utils 27 | The utils directory contains Sass partials like: 28 | * Vendor dependencies (Compass, Foundation) 29 | * Authored dependencies (Mixins, Extends) 30 | 31 | 2. Base 32 | 33 | The base directory contains Sass partials like: 34 | * Variables 35 | * Fonts 36 | * Reset 37 | 38 | 3. Layout 39 | 40 | The layout directory contains Sass partials like: 41 | * Responsive Grid 42 | * Page specific layouts 43 | 44 | 4. Modules 45 | 46 | The modules directory contains Sass partials like: 47 | * Header 48 | * Footer 49 | * Navigation 50 | * Content Block 51 | 52 | 5. Themes 53 | 54 | The themes directory contains Sass partials that overwrite the styles in layout or modules. 55 | 56 | ## Contributing 57 | 1. Fork it 58 | 2. Run `npm install` 59 | 3. Run `gulp` 60 | 4. Create your feature branch (`git checkout -b my-new-feature`) 61 | 5. Commit your changes (`git commit -am 'Add some feature'`) 62 | 6. Push to the branch (`git push origin my-new-feature`) 63 | 7. Create new Pull Request 64 | 65 | ## License 66 | MIT © [Ryan Burgess](http://github.com/ryanburgess) 67 | -------------------------------------------------------------------------------- /lib/commands/page.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var prompt = require('prompt'); 4 | var pkg = require('../../package.json'); 5 | var strings = require('../../templates/json/strings.json'); 6 | var write = require('../write'); 7 | var version = pkg.version; 8 | var dir = path.dirname(); 9 | var name; 10 | var filePath = 'sass'; 11 | var modules; 12 | var moduleBlock = ''; 13 | 14 | module.exports = function page() { 15 | prompt.message = 'SassySass'.magenta; 16 | prompt.delimiter = ' '; 17 | 18 | prompt.start(); 19 | 20 | prompt.get({ 21 | properties: { 22 | name: { 23 | description: strings.questions.namePage, 24 | conform: function(fileName) { 25 | return !fs.existsSync(dir + '/' + filePath + '/' + fileName + '.scss'); 26 | }, 27 | message: strings.errors.pageExists 28 | }, 29 | filePath: { 30 | description: strings.questions.pathToPage 31 | }, 32 | modules: { 33 | description: strings.questions.addModules 34 | } 35 | } 36 | }, function (err, result) { 37 | name = result.name.replace(/\s+/g, '-'); 38 | modules = result.modules; 39 | 40 | if (err) { 41 | return err; 42 | } 43 | 44 | // if page name is left blank set to default page 45 | if(name === '') { 46 | name = 'page'; 47 | } 48 | 49 | // if file path is left blank leave to default sass 50 | if(result.filePath !== '') { 51 | filePath = result.filePath; 52 | } 53 | 54 | if(modules !== '') { 55 | modules = modules.split(', '); 56 | for (var i = 0; i < modules.length; i++) { 57 | moduleBlock += '@import "modules/' + modules[i] + '";\n'; 58 | } 59 | } 60 | 61 | // check if file already exists 62 | fs.exists(dir + '/' + filePath + '/' + name + '.scss', function (exists) { 63 | 64 | if(exists !== true) { 65 | // create page specific 66 | fs.readFile(path.join(__dirname, '../../sass/style.scss'), 'utf8', function (err, data) { 67 | if (err) { 68 | console.log(strings.errros.directoryPath); 69 | return console.log(err); 70 | } 71 | var newFile = data.replace('@import "themes/red";', '').replace('@import "modules/header";', '') 72 | .replace('@import "modules/footer";', moduleBlock); 73 | write(dir + '/' + filePath + '/' + name + '.scss', newFile); 74 | }); 75 | 76 | console.log(strings.messages.pageVersion + version); 77 | }else { 78 | console.log('The page ' + name + ' already exists'); 79 | } 80 | }); 81 | }); 82 | }; -------------------------------------------------------------------------------- /sass/utils/_mixins.scss: -------------------------------------------------------------------------------- 1 | // SassySass ------------------------------------------------------------ 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | // Alignment 6 | 7 | // ---------------------------------------------------------------------- 8 | @import "mixins/margin-auto"; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | // Animation 13 | 14 | // ---------------------------------------------------------------------- 15 | @import "mixins/animate-link"; 16 | @import "mixins/animations"; 17 | @import "mixins/backface-visibility"; 18 | @import "mixins/keyframes"; 19 | @import "mixins/single-transform"; 20 | @import "mixins/transform"; 21 | @import "mixins/transitions"; 22 | @import "mixins/translate"; 23 | 24 | // ---------------------------------------------------------------------- 25 | 26 | // Functional 27 | 28 | // ---------------------------------------------------------------------- 29 | @import "mixins/hide-text"; 30 | @import "mixins/hover-focus"; 31 | @import "mixins/replace-text"; 32 | 33 | // ---------------------------------------------------------------------- 34 | 35 | // Gradients 36 | 37 | // ---------------------------------------------------------------------- 38 | @import "mixins/linear-gradient"; 39 | @import "mixins/linear-gradient-angle"; 40 | 41 | // ---------------------------------------------------------------------- 42 | 43 | // Layout 44 | 45 | // ---------------------------------------------------------------------- 46 | @import "mixins/background-cover"; 47 | @import "mixins/box-model"; 48 | @import "mixins/clearfix"; 49 | @import "mixins/inline-block"; 50 | @import "mixins/align-text"; 51 | 52 | // ---------------------------------------------------------------------- 53 | 54 | // Media Queries 55 | 56 | // ---------------------------------------------------------------------- 57 | @import "mixins/breakpoint"; 58 | @import "mixins/betweenbreakpoints"; 59 | @import "mixins/min-breakpoint"; 60 | @import "mixins/retina"; 61 | 62 | // ---------------------------------------------------------------------- 63 | 64 | // Styles 65 | 66 | // ---------------------------------------------------------------------- 67 | @import "mixins/box-shadow"; 68 | @import "mixins/inner-shadow"; 69 | @import "mixins/opacity"; 70 | @import "mixins/placeholder"; 71 | @import "mixins/rounded-corners"; 72 | @import "mixins/text-shadow"; 73 | @import "mixins/triangles"; 74 | 75 | // ---------------------------------------------------------------------- 76 | 77 | // Values 78 | 79 | // ---------------------------------------------------------------------- 80 | @import "mixins/rem"; -------------------------------------------------------------------------------- /lib/commands/explore.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var https = require('https'); 3 | var request = require('request'); 4 | var path = require('path'); 5 | var prompt = require('prompt'); 6 | var dir = path.dirname(); 7 | var mixinsPath = 'sass/utils'; 8 | var availableMixins = []; 9 | 10 | module.exports = function explore() { 11 | var options = { 12 | url: 'https://api.github.com/repositories/35896497/contents/utils/mixins', 13 | method: 'GET', 14 | headers: { 15 | 'User-Agent': 'Super Agent/0.0.1', 16 | 'Content-Type': 'application/x-www-form-urlencoded' 17 | } 18 | }; 19 | 20 | function startPrompt(json) { 21 | prompt.message = 'SassySass'.magenta; 22 | prompt.delimiter = ' '; 23 | 24 | prompt.start(); 25 | 26 | prompt.get({ 27 | properties: { 28 | mixinSelected: { 29 | description: 'What mixin would you like to install?\n'.red + json.map(function(name, index) { return index + '. ' + name; }).join('\n').white + '\n' 30 | } 31 | } 32 | }, 33 | function (err, result) { 34 | if(err) { 35 | return console.log(err); 36 | } 37 | 38 | var mixinFile = availableMixins[result.mixinSelected]; 39 | console.log(mixinFile); 40 | var file = fs.createWriteStream(dir + '/' + mixinsPath + '/mixins/' + mixinFile); 41 | var req = https.get('https://raw.githubusercontent.com/ryanburgess/sassysass/master/utils/mixins/' + mixinFile, function(response) { 42 | console.log(req); 43 | response.pipe(file); 44 | file.on('finish', function() { 45 | file.close(function (err) { 46 | if(err) { 47 | return console.log(err); 48 | } 49 | fs.appendFile(dir + '/' + mixinsPath + '/_mixins.scss', '@import \"mixins/' + mixinFile.substr(1).split('.scss')[0] + '\";\n', function (err) { 50 | if (err) { 51 | console.log(err); 52 | } 53 | }); 54 | console.log('\n Mixin ' + mixinFile + ' successfully added.'.magenta); 55 | }); // close() is async, call cb after close completes. 56 | }); 57 | }).on('error', function(err) { // Handle errors 58 | fs.unlink(dir + mixinsPath); // Delete the file async. (But we don't check the result) 59 | console.log(err); 60 | }); 61 | }); 62 | } 63 | 64 | // API Github requests user agent 65 | console.log('Fetching mixins...\n\n'.red); 66 | request(options, function (error, response, body) { 67 | if (!error) { 68 | JSON.parse(body).forEach(function (e) { 69 | availableMixins.push(e.name); 70 | }); 71 | startPrompt(availableMixins); 72 | } 73 | }); 74 | }; 75 | 76 | -------------------------------------------------------------------------------- /lib/commands/unused.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs-extra'); 2 | var path = require('path'); 3 | var prompt = require('prompt'); 4 | var dir = path.dirname(); 5 | var fileArr = []; 6 | var ouput = ''; 7 | 8 | function findFiles(type) { 9 | var files = fs.readdirSync(dir + '/sass/'); 10 | var num = 0; 11 | for (var i in files) { 12 | if(files[i].indexOf('.scss') !== -1) { 13 | var name = files[i]; 14 | 15 | fs.readFile(dir + '/sass/' + name, 'utf8', function(err, data) { 16 | if (err) { 17 | return err; 18 | } 19 | 20 | // loop through the unused files array 21 | fileArr.forEach(function(entry) { 22 | if(data.indexOf('@import "' + type + '/' + entry + '";') === -1) { 23 | ouput += '_' + entry + '.scss\n'; 24 | num++; 25 | } 26 | }); 27 | console.log('\nSassy Sass: there is currently ' + num + ' unused ' + type + '\n'); 28 | console.log(ouput); 29 | 30 | // prompt to ask if unused files should be deleted 31 | if(num >= 1) { 32 | prompt.message = 'SassySass'.magenta; 33 | prompt.delimiter = ' '; 34 | prompt.start(); 35 | prompt.get({ 36 | properties: { 37 | answer: { 38 | description: 'Do you want to delete unused ' + type + '? (yes/no)' 39 | } 40 | } 41 | }, function (err, result) { 42 | if (err) { 43 | return err; 44 | } 45 | 46 | // if user responds yes files will then be deleted 47 | if(result.answer === 'yes') { 48 | // loop through the unused files array 49 | fileArr.forEach(function(entry) { 50 | // unlink each unused file 51 | fs.unlink(dir + '/sass/' + type + '/_' + entry + '.scss', function (err) { 52 | if (err) { throw err; } 53 | }); 54 | }); 55 | console.log('Unused ' + type + ' have been deleted'); 56 | } 57 | }); 58 | } 59 | }); 60 | } 61 | } 62 | } 63 | 64 | module.exports = function unused(type) { 65 | if(type === 'modules' || type === 'layout' || type === 'themes') { 66 | var files = fs.readdirSync(dir + '/sass/' + type); 67 | for (var i in files) { 68 | if(files[i].indexOf('.scss') !== -1) { 69 | var name = files[i]; 70 | name = name.replace('_', '').replace('.scss', ''); 71 | // push unused files to an array 72 | fileArr.push(name); 73 | } 74 | } 75 | findFiles(type); 76 | }else { 77 | console.log('\nNot a command. Try sassysass unused \n'); 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /lib/commands/install.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs-extra'); 2 | var path = require('path'); 3 | var pkg = require('../../package.json'); 4 | var write = require('../write'); 5 | var mkdir = require('../mkdir'); 6 | var version = pkg.version; 7 | var dir = path.dirname(); 8 | 9 | module.exports = function install() { 10 | // check to make sure a sass directory doesn't exist already 11 | fs.exists(dir + '/sass', function (exists) { 12 | if(exists !== true) { 13 | mkdir(dir + '/sass', function() { 14 | mkdir(dir + '/sass/utils'); 15 | mkdir(dir + '/sass/base'); 16 | mkdir(dir + '/sass/layout'); 17 | mkdir(dir + '/sass/modules'); 18 | mkdir(dir + '/sass/themes'); 19 | 20 | // create files 21 | write(dir + '/sass/base/_fonts.scss', ''); 22 | write(dir + '/sass/layout/_grid.scss', ''); 23 | }); 24 | 25 | // copy the mixins directory and create a new mixins directory 26 | fs.copy(path.join(__dirname, '../../sass/utils/mixins'), dir + '/sass/utils/mixins', function(err) { 27 | if (err) { 28 | return console.log(err); 29 | } 30 | }); 31 | 32 | // create page specific 33 | fs.readFile(path.join(__dirname, '../../sass/style.scss'), 'utf8', function (err, data) { 34 | if (err) { 35 | return console.log(err); 36 | } 37 | write(dir + '/sass/style.scss', data); 38 | }); 39 | 40 | // create mixins 41 | fs.readFile(path.join(__dirname, '../../sass/utils/_mixins.scss'), 'utf8', function (err, data) { 42 | if (err) { 43 | return console.log(err); 44 | } 45 | write(dir + '/sass/utils/_mixins.scss', data); 46 | }); 47 | 48 | // create extends 49 | fs.readFile(path.join(__dirname, '../../sass/utils/_extends.scss'), 'utf8', function (err, data) { 50 | if (err) { 51 | return console.log(err); 52 | } 53 | write(dir + '/sass/utils/_extends.scss', data); 54 | }); 55 | 56 | // create reset 57 | fs.readFile(path.join(__dirname, '../../sass/base/_reset.scss'), 'utf8', function (err, data) { 58 | if (err) { 59 | return console.log(err); 60 | } 61 | write(dir + '/sass/base/_reset.scss', data); 62 | }); 63 | 64 | // create variables 65 | fs.readFile(path.join(__dirname, '../../sass/base/_variables.scss'), 'utf8', function (err, data) { 66 | if (err) { 67 | return console.log(err); 68 | } 69 | write(dir + '/sass/base/_variables.scss', data); 70 | }); 71 | 72 | console.log('SassySass v' + version); 73 | }else { 74 | console.log('A Sass directory already exists'); 75 | } 76 | }); 77 | }; -------------------------------------------------------------------------------- /lib/commands/mixin.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var write = require('../write'); 3 | var readline = require('readline'); 4 | var path = require('path'); 5 | var prompt = require('prompt'); 6 | var dir = path.dirname(); 7 | var mixinsPath = 'sass/utils'; 8 | var mixinSection = []; 9 | 10 | module.exports = function mixin() { 11 | 12 | function addImportStatement(section, mixinFileName) { 13 | var instream = fs.createReadStream(dir + '/' + mixinsPath + '/_mixins.scss'); 14 | var rl = readline.createInterface({ 15 | input: instream, 16 | terminal: false 17 | }); 18 | 19 | //silly logic to find line to insert @import statement 20 | var sectionLineNum = 0; 21 | var emptyLineCounter = 0; 22 | var foundEmptyLine = false; 23 | var foundSection = false; 24 | 25 | rl.on('line', function(line) { 26 | 27 | if(!foundSection) { 28 | sectionLineNum++; 29 | } 30 | if(foundSection) { 31 | if(!foundEmptyLine) { 32 | sectionLineNum++; 33 | } 34 | if(line === '') { 35 | emptyLineCounter++; 36 | } 37 | if(emptyLineCounter === 2) { 38 | foundEmptyLine = true; 39 | } 40 | } 41 | if(line.indexOf(section) > -1) { 42 | foundSection = true; 43 | } 44 | }); 45 | 46 | rl.on('close', function() { 47 | 48 | //write @import statement 49 | var data = fs.readFileSync(dir + '/' + mixinsPath + '/_mixins.scss').toString().split('\n'); 50 | data.splice(sectionLineNum - 1, 0, '@import "mixins/' + mixinFileName + '";'); 51 | var text = data.join('\n'); 52 | fs.writeFile(dir + '/' + mixinsPath + '/_mixins.scss', text, function (err) { 53 | if (err) { 54 | return console.log(err); 55 | } 56 | }); 57 | 58 | console.log('\nSassySass mixin ' + mixinFileName + ' was successfully created.\n'); 59 | }); 60 | } 61 | 62 | function startPrompt() { 63 | 64 | prompt.start(); 65 | 66 | prompt.message = 'SassySass'.magenta; 67 | prompt.delimiter = ' '; 68 | 69 | prompt.get({ 70 | properties: { 71 | section: { 72 | description: 'Choose Section for New Mixin:\n'.red + mixinSection.map(function (section, index) { 73 | return index + '. ' + section; 74 | }).join('\n').white + '\n' 75 | }, 76 | mixinName: { 77 | description: 'Enter a Name for New Mixin:'.red 78 | } 79 | } 80 | }, function (err, result) { 81 | if(err) { 82 | return err; 83 | } 84 | //create new mixin file 85 | //need to validation to check for existing mixin file 86 | var mixinFileName = result.mixinName.replace(/\s+/g, '-').toLowerCase(); 87 | write(dir + '/' + mixinsPath + '/mixins/' + '_' + mixinFileName + '.scss', ''); 88 | addImportStatement(mixinSection[parseInt(result.section)], mixinFileName); 89 | }); 90 | 91 | } 92 | 93 | var instream = fs.createReadStream(dir + '/' + mixinsPath + '/_mixins.scss'); 94 | var rl = readline.createInterface({ 95 | input: instream, 96 | terminal: false 97 | }); 98 | 99 | rl.on('line', function(line) { 100 | var result = line.match(/\s\s\/\/\s(\w+)(\s)?(\w+)/g); // matches space space // space NAME 101 | if(result !== null) { 102 | mixinSection.push(result[0].replace(' // ', '')); //strip leading slashes 103 | } 104 | }); 105 | 106 | rl.on('close', function() { 107 | mixinSection.push('*Add New Section*'); 108 | startPrompt(); 109 | }); 110 | 111 | }; 112 | -------------------------------------------------------------------------------- /lib/commands/theme.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var prompt = require('prompt'); 6 | var async = require('async'); 7 | var pkg = require('../../package.json'); 8 | var strings = require('../../templates/json/strings.json'); 9 | var version = pkg.version; 10 | var dir = path.dirname(); 11 | var dateTime = require('get-date'); 12 | var newFile = ''; 13 | var pageBlock = ''; 14 | var pages; 15 | var name; 16 | var themePath = 'sass/themes'; 17 | var themeDesc; 18 | 19 | module.exports = function theme() { 20 | 21 | function writeFile() { 22 | fs.writeFile(dir + '/' + themePath + '/_' + name + '.scss', newFile, function(err) { 23 | if(err) { 24 | console.log(err); 25 | console.log(strings.errors.directoryPath); 26 | }else { 27 | console.log('_' + name + '.scss was created'); 28 | } 29 | console.log(strings.messages.themeVersion + version); 30 | }); 31 | } 32 | 33 | // complete the creation of the new theme 34 | function complete() { 35 | newFile += '// File Name: _' + name + '.scss' + '\n'; 36 | newFile += '// Description: ' + themeDesc + '\n'; 37 | newFile += '// Used by: ' + pageBlock + '\n'; 38 | newFile += '// Dependencies: \n'; 39 | newFile += '// Date created: ' + dateTime() + '\n'; 40 | newFile += '// SassySass v' + version + '\n'; 41 | newFile += '// ------------------------------------------------------------\n'; 42 | // check if file already exists 43 | fs.exists(dir + '/' + themePath + '/_' + name + '.scss', function (exists) { 44 | if(exists !== true) { 45 | writeFile(); 46 | }else { 47 | console.log('The theme ' + name + ' already exists'); 48 | } 49 | }); 50 | } 51 | 52 | prompt.message = 'SassySass'.magenta; 53 | prompt.delimiter = ' '; 54 | 55 | prompt.start(); 56 | 57 | prompt.get({ 58 | properties: { 59 | name: { 60 | description: strings.questions.nameTheme, 61 | conform: function(themeName) { 62 | return !fs.existsSync(dir + '/' + themePath + '/_' + themeName + '.scss'); 63 | }, 64 | message: strings.errors.themeExists 65 | }, 66 | themePath: { 67 | description: strings.questions.pathToTheme 68 | }, 69 | themeDesc: { 70 | description: strings.questions.themeDesc 71 | }, 72 | pages: { 73 | description: strings.questions.themeAddToPage 74 | } 75 | } 76 | }, function (err, result) { 77 | name = result.name.replace(/\s+/g, '-'); 78 | themeDesc = result.themeDesc; 79 | pages = result.pages; 80 | 81 | if(err) { 82 | return err; 83 | } 84 | 85 | // if theme name is left blank set to default theme 86 | if(name === '') { 87 | name = 'theme'; 88 | } 89 | 90 | // if file path is left blank set to default sass/themes 91 | if(result.themePath !== '') { 92 | themePath = result.themePath; 93 | } 94 | 95 | // add theme to the list of pages provided 96 | if(pages !== '') { 97 | pages = pages.split(', '); 98 | 99 | async.forEach(pages, function (page, callback) { 100 | 101 | pageBlock += page + '.scss, '; 102 | 103 | fs.exists(dir + '/sass/' + page + '.scss', function (exists) { 104 | if(exists === true) { 105 | var newThemePath = themePath.replace('sass/', ''); 106 | fs.appendFile(dir + '/sass/' + page + '.scss', '\n@import "' + newThemePath + '/' + name + '";', function(err) { 107 | if (err) { 108 | return console.log(err); 109 | } 110 | }); 111 | } 112 | }); 113 | 114 | callback(); 115 | }, function(err) { 116 | if(err) { 117 | return err; 118 | } 119 | complete(); 120 | }); 121 | }else { 122 | complete(); 123 | } 124 | }); 125 | }; -------------------------------------------------------------------------------- /lib/commands/module.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var prompt = require('prompt'); 6 | var async = require('async'); 7 | var pkg = require('../../package.json'); 8 | var strings = require('../../templates/json/strings.json'); 9 | var version = pkg.version; 10 | var dir = path.dirname(); 11 | var dateTime = require('get-date'); 12 | var write = require('../write'); 13 | var newFile = ''; 14 | var pageBlock = ''; 15 | var pages; 16 | var name; 17 | var modulePath = 'sass/modules'; 18 | var moduleDesc; 19 | 20 | module.exports = function module() { 21 | 22 | function writeFile() { 23 | fs.writeFile(dir + '/' + modulePath + '/_' + name + '.scss', newFile, function(err) { 24 | if(err) { 25 | console.log(err); 26 | console.log(strings.errors.directoryPath); 27 | }else { 28 | console.log('_' + name + '.scss was created'); 29 | } 30 | console.log(strings.messages.moduleVersion + version); 31 | }); 32 | } 33 | 34 | // complete the creation of the new module 35 | function complete() { 36 | newFile += '// File Name: _' + name + '.scss' + '\n'; 37 | newFile += '// Description: ' + moduleDesc + '\n'; 38 | newFile += '// Used by: ' + pageBlock + '\n'; 39 | newFile += '// Dependencies: \n'; 40 | newFile += '// Date created: ' + dateTime() + '\n'; 41 | newFile += '// SassySass v' + version + '\n'; 42 | newFile += '// ------------------------------------------------------------\n'; 43 | 44 | // check if file already exists 45 | fs.exists(dir + '/' + modulePath + '/_' + name + '.scss', function (exists) { 46 | if(exists !== true) { 47 | writeFile(); 48 | }else { 49 | console.log('The module ' + name + ' already exists'); 50 | } 51 | }); 52 | } 53 | 54 | prompt.message = 'SassySass'.magenta; 55 | prompt.delimiter = ' '; 56 | 57 | prompt.start(); 58 | 59 | prompt.get({ 60 | properties: { 61 | name: { 62 | description: strings.questions.nameModule, 63 | conform: function(moduleName) { 64 | return !fs.existsSync(dir + '/' + modulePath + '/_' + moduleName + '.scss'); 65 | }, 66 | message: strings.errors.moduleExists 67 | }, 68 | modulePath: { 69 | description: strings.questions.pathToModule 70 | }, 71 | moduleDesc: { 72 | description: strings.questions.moduleDesc 73 | }, 74 | pages: { 75 | description: strings.questions.moduleAddToPage 76 | } 77 | } 78 | }, function (err, result) { 79 | name = result.name.replace(/\s+/g, '-'); 80 | moduleDesc = result.moduleDesc; 81 | pages = result.pages; 82 | 83 | if(err) { 84 | return err; 85 | } 86 | 87 | // if module name is left blank set to default module 88 | if(name === '') { 89 | name = 'module'; 90 | } 91 | 92 | // if file path is left blank set to default sass/modules 93 | if(result.modulePath !== '') { 94 | modulePath = result.modulePath; 95 | } 96 | 97 | // add module to the list of pages provided 98 | if(pages !== '') { 99 | pages = pages.split(', '); 100 | 101 | async.forEach(pages, function (page, callback) { 102 | 103 | pageBlock += page + '.scss, '; 104 | 105 | fs.exists(dir + '/sass/' + page + '.scss', function (exists) { 106 | if(exists === true) { 107 | fs.readFile(path.join(dir + '/sass/' + page + '.scss'), 'utf8', function (err, data) { 108 | if (err) { 109 | return console.log(err); 110 | } 111 | var newModPath = modulePath.replace('sass/', ''); 112 | var updateFile = data.replace('\n// ----------------------------------------------------------------------\n // Themes', 113 | '@import "' + newModPath + '/' + name + '";\n\n// ----------------------------------------------------------------------\n // Themes'); 114 | write(dir + '/sass/' + page + '.scss', updateFile); 115 | }); 116 | } 117 | }); 118 | 119 | callback(); 120 | }, function(err) { 121 | if(err) { 122 | return err; 123 | } 124 | complete(); 125 | }); 126 | }else { 127 | complete(); 128 | } 129 | }); 130 | }; -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "arrowFunctions": true, 4 | "binaryLiterals": false, 5 | "blockBindings": true, 6 | "classes": true, 7 | "defaultParams": true, 8 | "destructuring": true, 9 | "forOf": true, 10 | "generators": true, 11 | "modules": false, 12 | "objectLiteralComputedProperties": true, 13 | "objectLiteralDuplicateProperties": false, 14 | "objectLiteralShorthandMethods": true, 15 | "objectLiteralShorthandProperties": true, 16 | "octalLiterals": false, 17 | "regexUFlag": false, 18 | "regexYFlag": false, 19 | "restParams": true, 20 | "spread": true, 21 | "superInFunctions": true, 22 | "templateStrings": true, 23 | "unicodePointEscapes": true, 24 | "globalReturn": false, 25 | "jsx": true, 26 | "modules": true 27 | }, 28 | "env": { 29 | "browser": false, 30 | "node": true, 31 | "es6": false 32 | }, 33 | "parser": "babel-eslint", 34 | "plugins": [ 35 | "babel" 36 | ], 37 | "rules": { 38 | 39 | /*Possible Errors */ 40 | "comma-dangle": [2, "never"], 41 | "no-cond-assign": [1, "except-parens"], 42 | "no-console": 0, 43 | "no-constant-condition": 1, 44 | "no-control-regex": 1, 45 | "no-debugger": 1, 46 | "no-dupe-args": 1, 47 | "no-dupe-keys": 1, 48 | "no-duplicate-case": 0, 49 | "no-empty-character-class": 1, 50 | "no-empty": 1, 51 | "no-ex-assign": 1, 52 | "no-extra-boolean-cast": 1, 53 | "no-extra-parens": 0, 54 | "no-extra-semi": 1, 55 | "no-func-assign": 1, 56 | "no-inner-declarations": [1, "functions"], 57 | "no-invalid-regexp": 1, 58 | "no-irregular-whitespace": 1, 59 | "no-negated-in-lhs": 1, 60 | "no-obj-calls": 1, 61 | "no-regex-spaces": 1, 62 | "no-reserved-keys": 0, 63 | "no-sparse-arrays": 1, 64 | "no-unexpected-multiline": 1, 65 | "no-unreachable": 1, 66 | "use-isnan": 1, 67 | "valid-jsdoc": 1, 68 | "valid-typeof": 1, 69 | 70 | /* Best Practices */ 71 | "accessor-pairs": 0, 72 | "block-scoped-var": 0, // see Babel section 73 | "complexity": 0, 74 | "consistent-return": 1, 75 | "curly": [1, "all"], 76 | "default-case": 0, 77 | "dot-notation": [1, { "allowKeywords": true, "allowPattern": "" }], 78 | "dot-location": [1, "property"], 79 | "eqeqeq": 1, 80 | "guard-for-in": 0, 81 | "no-alert": 1, 82 | "no-caller": 1, 83 | "no-div-regex": 1, 84 | "no-else-return": 1, 85 | "no-empty-label": 1, 86 | "no-eq-null": 0, 87 | "no-eval": 1, 88 | "no-extend-native": 1, 89 | "no-extra-bind": 1, 90 | "no-fallthrough": 0, 91 | "no-floating-decimal": 1, 92 | "no-implied-eval": 1, 93 | "no-iterator": 1, 94 | "no-labels": 1, 95 | "no-lone-blocks": 1, 96 | //"no-loop-func": 1, 97 | "no-multi-spaces": 1, 98 | "no-multi-str": 1, 99 | "no-native-reassign": 1, 100 | "no-new-func": 1, 101 | "no-new-wrappers": 1, 102 | "no-new": 1, 103 | "no-octal-escape": 1, 104 | "no-octal": 1, 105 | "no-param-reassign": 0, 106 | "no-process-env": 0, 107 | "no-proto": 1, 108 | "no-redeclare": 1, 109 | "no-return-assign": 1, 110 | "no-script-url": 1, 111 | "no-self-compare": 1, 112 | "no-sequences": 1, 113 | "no-throw-literal": 1, 114 | "no-unused-expressions": 0, 115 | "no-void": 0, 116 | "no-warning-comments": [1, { "terms": ["todo", "tofix"], "location": "start" }], 117 | "no-with": 1, 118 | //"radix": 1, 119 | //"vars-on-top": 1, 120 | "wrap-iife": [1, "inside"], 121 | "yoda": [1, "never"], 122 | 123 | /* Strict Mode */ 124 | "strict": [1, "never"], 125 | 126 | /* Variables */ 127 | "no-catch-shadow": 0, 128 | "no-delete-var": 1, 129 | "no-label-var": 1, 130 | //"no-shadow-restricted-names": 1, 131 | //"no-shadow": 1, 132 | "no-undef-init": 1, 133 | "no-undef": 2, 134 | //"no-undefined": 1, 135 | "no-unused-vars": [1, { "vars": "local", "args": "after-used" }], 136 | "no-use-before-define": 1, 137 | 138 | /* Node.js */ 139 | "handle-callback-err": 1, 140 | "no-mixed-requires": 1, 141 | "no-new-require": 1, 142 | "no-path-concat": 1, 143 | "no-process-exit": 1, 144 | "no-restricted-modules": [1, ""], // add any unwanted Node.js core modules 145 | //"no-sync": 1, 146 | 147 | /* Stylistic Issues */ 148 | "array-bracket-spacing": [1, "never"], 149 | "camelcase": [1, { "properties": "always" }], 150 | "comma-spacing": [1, { "before": false, "after": true }], 151 | "comma-style": [1, "last"], 152 | "computed-property-spacing": 0, 153 | "consistent-this": 0, 154 | "eol-last": 0, 155 | //"func-names": 1, 156 | "func-style": 0, 157 | //"indent": [1, 2], 158 | "key-spacing": [1, { "beforeColon": false, "afterColon": true }], 159 | "linebreak-style": 0, 160 | "max-nested-callbacks": [0, 3], 161 | "new-cap": 0, // see Babel section 162 | "new-parens": 1, 163 | "newline-after-var": 0, 164 | "no-array-constructor": 1, 165 | "no-continue": 1, 166 | "no-inline-comments": 0, 167 | "no-lonely-if": 1, 168 | "no-mixed-spaces-and-tabs": 1, 169 | "no-multiple-empty-lines": [1, { "max": 1 }], 170 | "no-nested-ternary": 0, 171 | "no-new-object": 1, 172 | "no-spaced-func": 1, 173 | "no-ternary": 0, 174 | "no-trailing-spaces": 1, 175 | "no-underscore-dangle": 0, 176 | "no-unneeded-ternary": 1, 177 | "object-curly-spacing": 0, // see Babel section 178 | "one-var": [1, "never"], 179 | //"operator-assignment": [1, "never"], 180 | "padded-blocks": [0, "never"], 181 | "quote-props": [0, "as-needed"], 182 | "quotes": [1, "single"], 183 | "semi-spacing": [1, { "before": false, "after": true }], 184 | "semi": [1, "always"], 185 | "sort-vars": 0, 186 | "space-after-keywords": 0, 187 | "space-before-blocks": [1, "always"], 188 | //"space-before-function-paren": [1, "never"], 189 | "space-in-parens": [1, "never"], 190 | "space-infix-ops": 1, 191 | "space-return-throw-case": 1, 192 | "space-unary-ops": 0, 193 | //"spaced-comment": [1, "always"], 194 | "wrap-regex": 1, 195 | 196 | /* ECMAScript 6 */ 197 | //"constructor-super": 1, 198 | //"generator-star-spacing": 0, // see Babel section 199 | //"no-this-before-super": 1, 200 | //"no-var": 1, 201 | //"object-shorthand": 0, // see Babel section 202 | //"prefer-const": 1, 203 | 204 | /* Legacy */ 205 | "max-depth": [0, 3], 206 | "max-len": [1, 160, 2], 207 | "max-params": 0, 208 | "max-statements": 0, 209 | "no-bitwise": 1, 210 | //"no-plusplus": 1, 211 | } 212 | } --------------------------------------------------------------------------------