├── .babelrc ├── .editorconfig ├── .gitignore ├── README.md ├── app ├── blocks │ ├── footer │ │ ├── footer.jade │ │ └── footer.styl │ ├── head │ │ └── head.jade │ └── header │ │ ├── header.jade │ │ └── header.styl ├── jade-tools │ └── scripts.jade ├── layouts │ └── main.jade ├── pages │ └── index.jade ├── scripts │ ├── main.js │ ├── modules │ │ └── .gitkeep │ └── vendor │ │ └── .gitkeep ├── static │ └── assets │ │ ├── fonts │ │ └── .gitkeep │ │ └── images │ │ └── .gitkeep ├── styles │ ├── _mixins.styl │ ├── _variables.styl │ ├── base │ │ ├── core.styl │ │ ├── fonts.styl │ │ ├── reset.styl │ │ └── utilities.styl │ └── main.styl └── svg │ └── .gitkeep ├── block.sh ├── gulp ├── paths.js ├── tasks │ ├── build.js │ ├── clean.js │ ├── default.js │ ├── livereload.js │ ├── markup.js │ ├── scripts.js │ ├── static.js │ ├── styles.js │ ├── watch.js │ └── zip.js └── utils │ └── errorHandler.js ├── gulpfile.js └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | charset = utf-8 9 | indent_style = tab 10 | indent_size = 2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Стартанул 2 | 3 | Базовый шаблон для вёрстки проекта. 4 | 5 | Для разметки используется Jade + bemto, для стилей — Stylus + PostCSS, для скриптов — Browserify + ES6. 6 | 7 | ## Разработка и сборка 8 | Запуск локального сервера с автоматическим обновлением для разработки — `gulp`. 9 | 10 | Полная пересборка проекта с генерацией zip-архива в директории `dist/dist.zip` — `gulp build`. -------------------------------------------------------------------------------- /app/blocks/footer/footer.jade: -------------------------------------------------------------------------------- 1 | mixin footer() 2 | +b.footer&attributes(attributes) 3 | -------------------------------------------------------------------------------- /app/blocks/footer/footer.styl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrew--r/startanul/3842195ec8983e59d6b7a8828b18d553c11dcd8d/app/blocks/footer/footer.styl -------------------------------------------------------------------------------- /app/blocks/head/head.jade: -------------------------------------------------------------------------------- 1 | head 2 | meta(charset='utf-8') 3 | meta(name='viewport' content='width=device-width, initial-scale=1, minimal-ui') 4 | meta(http-equiv='X-UA-Compatible' content='IE=edge') 5 | 6 | meta(name='imagetoolbar' content='no') 7 | meta(name='msthemecompatible' content='no') 8 | meta(name='cleartype' content='on') 9 | meta(name='HandheldFriendly' content='True') 10 | meta(name='google' value='notranslate') 11 | 12 | link(rel='shortcut icon' type='image/png' href='favicon.png') 13 | 14 | meta(name='description' content='') 15 | meta(name='keywords' content='') 16 | 17 | block head 18 | title= pageTitle || 'Заголовок страницы' 19 | 20 | link(href='assets/styles/main.min.css?t=' + timestamp rel='stylesheet') 21 | -------------------------------------------------------------------------------- /app/blocks/header/header.jade: -------------------------------------------------------------------------------- 1 | mixin header() 2 | +b.header&attributes(attributes) 3 | -------------------------------------------------------------------------------- /app/blocks/header/header.styl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrew--r/startanul/3842195ec8983e59d6b7a8828b18d553c11dcd8d/app/blocks/header/header.styl -------------------------------------------------------------------------------- /app/jade-tools/scripts.jade: -------------------------------------------------------------------------------- 1 | mixin scripts(scripts) 2 | each src in scripts 3 | - var isExternalScript = /^(?:https?\:)?\/\//i; 4 | - src = isExternalScript.test(src) ? src : '/assets/scripts/' + src; 5 | script(src=src) -------------------------------------------------------------------------------- /app/layouts/main.jade: -------------------------------------------------------------------------------- 1 | include ../../node_modules/bemto.jade/bemto 2 | - set_bemto_settings({ modifier: '--' }) 3 | 4 | include ../jade-tools/scripts 5 | 6 | include ../blocks/header/header 7 | include ../blocks/footer/footer 8 | 9 | doctype html 10 | html(lang='ru') 11 | include ../blocks/head/head 12 | body 13 | +header() 14 | block content 15 | +footer() 16 | block scripts 17 | +scripts(['build.js']) 18 | -------------------------------------------------------------------------------- /app/pages/index.jade: -------------------------------------------------------------------------------- 1 | extends ../layouts/main 2 | 3 | block head 4 | - var pageTitle = 'Главная'; 5 | 6 | block content 7 | -------------------------------------------------------------------------------- /app/scripts/main.js: -------------------------------------------------------------------------------- 1 | console.log('hello world!'); -------------------------------------------------------------------------------- /app/scripts/modules/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrew--r/startanul/3842195ec8983e59d6b7a8828b18d553c11dcd8d/app/scripts/modules/.gitkeep -------------------------------------------------------------------------------- /app/scripts/vendor/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrew--r/startanul/3842195ec8983e59d6b7a8828b18d553c11dcd8d/app/scripts/vendor/.gitkeep -------------------------------------------------------------------------------- /app/static/assets/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrew--r/startanul/3842195ec8983e59d6b7a8828b18d553c11dcd8d/app/static/assets/fonts/.gitkeep -------------------------------------------------------------------------------- /app/static/assets/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrew--r/startanul/3842195ec8983e59d6b7a8828b18d553c11dcd8d/app/static/assets/images/.gitkeep -------------------------------------------------------------------------------- /app/styles/_mixins.styl: -------------------------------------------------------------------------------- 1 | // Центрирование по горизонтали блока заданной ширины 2 | container($width) 3 | width $width 4 | margin-left auto 5 | margin-right auto 6 | 7 | 8 | // Размеры элемента 9 | size($width, $height = $width) 10 | width $width 11 | height $height 12 | 13 | 14 | // Центрирование по горизонтали 15 | center() 16 | margin-right auto 17 | margin-left auto 18 | 19 | 20 | // Центрирование абсолютно позиционированного элемента по вертикали 21 | absolute-center() 22 | position absolute 23 | top 50% 24 | transform translateY(-50%) 25 | 26 | 27 | // Сброс обтекания для плавающих блоков-потомков 28 | clearfix() 29 | &:before, 30 | &:after 31 | content " " 32 | display table 33 | 34 | &:after 35 | clear both 36 | 37 | 38 | // Применяется к родительскому блоку, в который вложено n inline-block потомков. 39 | // Эти потомки будут распределены по ширине родительского блока 40 | justify() 41 | font-size 1px 42 | line-height 0 43 | 44 | zoom 1 45 | 46 | text-align justify 47 | text-align-last justify 48 | text-justify newspaper 49 | 50 | &:after 51 | display inline-block 52 | visibility hidden 53 | 54 | overflow hidden 55 | 56 | width 100% 57 | height 0 58 | 59 | content '' 60 | 61 | 62 | // Применяется к inline-block элементам, вложенным в родителя с применённым justify. 63 | // Следует указать нужный размер шрифта в блоках, так как в justify он сбрасывается 64 | justify-child(font-size = 16px) 65 | display inline-block 66 | vertical-align top 67 | 68 | font-size font-size 69 | line-height normal 70 | 71 | 72 | 73 | // Красивое обрезание лишнего текста 74 | text-overflow() 75 | overflow hidden 76 | white-space nowrap 77 | text-overflow ellipsis 78 | 79 | 80 | // Скрытие текста у блока 81 | hidetext() 82 | font 0/0 a 83 | text-shadow none 84 | color transparent 85 | 86 | 87 | // Запрет выделения текста 88 | noselection() 89 | user-select none 90 | -webkit-touch-callout none 91 | 92 | &:hover 93 | cursor default 94 | 95 | 96 | // Задаёт цвет плейсхолдера 97 | placeholder-color(color) 98 | &:-moz-placeholder, 99 | &::-moz-placeholder 100 | color color 101 | opacity 1 102 | 103 | &::-webkit-input-placeholder 104 | color color 105 | 106 | 107 | // Хак для включения аппаратного ускорения. 108 | // Поддержка браузерами: IE10+ 109 | gpu() 110 | transform translate3d(0, 0, 0) 111 | 112 | 113 | // Фоновая картинка 114 | image-bg(name) 115 | background-image url('../images/' + name) 116 | background-size cover 117 | 118 | 119 | // Хелперы для флексбокса 120 | flex-center() 121 | display flex 122 | align-items center 123 | justify-content center 124 | 125 | 126 | flexible() 127 | flex-grow 1 128 | flex-shrink 1 129 | 130 | 131 | unflexible() 132 | flex-grow 0 133 | flex-shrink 0 134 | -------------------------------------------------------------------------------- /app/styles/_variables.styl: -------------------------------------------------------------------------------- 1 | // Responsive stuff 2 | $desktop = 1024px 3 | $mobile = 480px 4 | 5 | 6 | // Fonts 7 | $fontSize = 16px 8 | $lineHeight = 1.4 9 | $baseLine = $fontSize * $lineHeight 10 | $fontFamily = 'Helvetica Neue', Helvetica, Arial, sans-serif 11 | -------------------------------------------------------------------------------- /app/styles/base/core.styl: -------------------------------------------------------------------------------- 1 | html, body 2 | height 100% 3 | 4 | 5 | body 6 | font-size $fontSize 7 | line-height $lineHeight 8 | font-family $fontFamily 9 | 10 | 11 | a 12 | text-decoration none 13 | 14 | transition all .2s ease 15 | 16 | &:hover 17 | transition none -------------------------------------------------------------------------------- /app/styles/base/fonts.styl: -------------------------------------------------------------------------------- 1 | // Regular 2 | @font-face 3 | font-family 'Name' 4 | src url('../fonts/name/regular.woff2') format('woff2'), 5 | url('../fonts/name/regular.woff') format('woff') 6 | font-style normal 7 | font-weight 400 8 | 9 | 10 | // Bold 11 | @font-face 12 | font-family 'Name' 13 | src url('../fonts/name/bold.woff2') format('woff2'), 14 | url('../fonts/name/bold.woff') format('woff') 15 | font-style normal 16 | font-weight 700 -------------------------------------------------------------------------------- /app/styles/base/reset.styl: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | html 4 | font-family sans-serif 5 | -ms-text-size-adjust 100% 6 | -webkit-text-size-adjust 100% 7 | 8 | 9 | body 10 | margin 0 11 | 12 | 13 | article, 14 | aside, 15 | details, 16 | figcaption, 17 | figure, 18 | footer, 19 | header, 20 | hgroup, 21 | main, 22 | menu, 23 | nav, 24 | section, 25 | summary 26 | display block 27 | 28 | 29 | audio, 30 | canvas, 31 | progress, 32 | video 33 | display inline-block 34 | vertical-align baseline 35 | 36 | 37 | audio:not([controls]) 38 | display none 39 | height 0 40 | 41 | 42 | a 43 | background-color transparent 44 | 45 | &:active, 46 | &:hover 47 | outline 0 48 | 49 | 50 | abbr[title] 51 | border-bottom 1px dotted 52 | 53 | 54 | b, 55 | strong 56 | font-weight bold 57 | 58 | 59 | dfn 60 | font-style italic 61 | 62 | 63 | mark 64 | background #ff0 65 | color #000 66 | 67 | 68 | small 69 | font-size 80% 70 | 71 | 72 | sub, 73 | sup 74 | font-size 75% 75 | line-height 0 76 | position relative 77 | vertical-align baseline 78 | 79 | 80 | sup 81 | top -0.5em 82 | 83 | 84 | sub 85 | bottom -0.25em 86 | 87 | 88 | img 89 | border 0 90 | 91 | 92 | svg:not(:root) 93 | overflow hidden 94 | 95 | 96 | hr 97 | box-sizing content-box 98 | height 0 99 | 100 | 101 | pre 102 | overflow auto 103 | 104 | 105 | code, 106 | kbd, 107 | pre, 108 | samp 109 | font-family monospace, monospace 110 | font-size 1em 111 | 112 | 113 | button, 114 | input, 115 | optgroup, 116 | select, 117 | textarea 118 | color inherit 119 | font inherit 120 | margin 0 121 | 122 | 123 | button 124 | overflow visible 125 | 126 | 127 | button, 128 | select 129 | text-transform none 130 | 131 | 132 | button, 133 | html input[type="button"], 134 | input[type="reset"], 135 | input[type="submit"] 136 | -webkit-appearance button 137 | cursor pointer 138 | 139 | 140 | button[disabled], 141 | html input[disabled] 142 | cursor default 143 | 144 | 145 | button::-moz-focus-inner, 146 | input::-moz-focus-inner 147 | border 0 148 | padding 0 149 | 150 | 151 | input 152 | line-height normal 153 | 154 | 155 | input[type="checkbox"], 156 | input[type="radio"] 157 | box-sizing border-box 158 | padding 0 159 | 160 | 161 | input[type="number"]::-webkit-inner-spin-button, 162 | input[type="number"]::-webkit-outer-spin-button 163 | height auto 164 | 165 | 166 | input[type="search"] 167 | -webkit-appearance textfield 168 | box-sizing content-box 169 | 170 | 171 | input[type="search"]::-webkit-search-cancel-button, 172 | input[type="search"]::-webkit-search-decoration 173 | -webkit-appearance none 174 | 175 | legend 176 | border 0 177 | padding 0 178 | 179 | 180 | textarea 181 | overflow auto 182 | 183 | optgroup 184 | font-weight bold 185 | 186 | 187 | table 188 | border-collapse collapse 189 | border-spacing 0 190 | 191 | 192 | td, 193 | th 194 | padding 0 195 | 196 | 197 | // reset all default margins and paddings 198 | html, 199 | body, 200 | div, 201 | span, 202 | applet, 203 | object, 204 | iframe, 205 | h1, 206 | h2, 207 | h3, 208 | h4, 209 | h5, 210 | h6, 211 | p, 212 | blockquote, 213 | pre, 214 | a, 215 | abbr, 216 | acronym, 217 | address, 218 | big, 219 | cite, 220 | code, 221 | del, 222 | dfn, 223 | em, 224 | img, 225 | ins, 226 | kbd, 227 | q, 228 | s, 229 | samp, 230 | small, 231 | strike, 232 | strong, 233 | sub, 234 | sup, 235 | tt, 236 | var, 237 | b, 238 | u, 239 | i, 240 | center, 241 | dl, 242 | dt, 243 | dd, 244 | ol, 245 | ul, 246 | li, 247 | fieldset, 248 | form, 249 | label, 250 | legend, 251 | table, 252 | caption, 253 | tbody, 254 | tfoot, 255 | thead, 256 | tr, 257 | th, 258 | td, 259 | article, 260 | aside, 261 | canvas, 262 | details, 263 | embed, 264 | figure, 265 | figcaption, 266 | footer, 267 | header, 268 | hgroup, 269 | menu, 270 | nav, 271 | output, 272 | ruby, 273 | section, 274 | summary, 275 | time, 276 | mark, 277 | audio, 278 | video 279 | margin 0 280 | padding 0 281 | vertical-align baseline 282 | 283 | 284 | // Пользовательские стили 285 | 286 | // Предотвращаем изменение ширины сайта при появлении скролла 287 | body 288 | overflow-y scroll 289 | 290 | 291 | // Заменяем длинный текст placeholder многоточием 292 | input[placeholder], 293 | input:-moz-placeholder, 294 | input::-moz-placeholder, 295 | input:-ms-input-placeholder 296 | text-overflow ellipsis 297 | 298 | 299 | // Убираем крестик у поля ввода в inherit 300 | input::-ms-clear 301 | display none 302 | 303 | 304 | // Курсор для label + отмена выделения при клике 305 | label 306 | noselection() 307 | cursor pointer 308 | 309 | 310 | // Корректное отображение изображений 311 | img 312 | width auto\9 313 | max-width 100% 314 | height auto -------------------------------------------------------------------------------- /app/styles/base/utilities.styl: -------------------------------------------------------------------------------- 1 | .u-nobr 2 | white-space nowrap -------------------------------------------------------------------------------- /app/styles/main.styl: -------------------------------------------------------------------------------- 1 | @import '_variables' 2 | @import '_mixins' 3 | 4 | rupture.desktop-cutoff = $desktop 5 | rupture.mobile-cutoff = $mobile 6 | 7 | @import 'base/reset' 8 | @import 'base/core' 9 | @import 'base/utilities' 10 | 11 | @import '../blocks/header/*' 12 | @import '../blocks/footer/*' 13 | -------------------------------------------------------------------------------- /app/svg/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrew--r/startanul/3842195ec8983e59d6b7a8828b18d553c11dcd8d/app/svg/.gitkeep -------------------------------------------------------------------------------- /block.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir app/blocks/$1 3 | touch app/blocks/$1/$1.styl 4 | touch app/blocks/$1/$1.jade 5 | 6 | echo -e "@import '../blocks/$1/*'" >> app/styles/main.styl 7 | echo -e "mixin $1()\n\t+b.$1&attributes(attributes)" >> app/blocks/$1/$1.jade 8 | echo -e ".$1" >> app/blocks/$1/$1.styl 9 | 10 | echo "Блок $1 создан" 11 | -------------------------------------------------------------------------------- /gulp/paths.js: -------------------------------------------------------------------------------- 1 | export default { 2 | baseSrc: './app', 3 | baseDist: './dist', 4 | 5 | src: { 6 | styles: './app/styles', 7 | svg: './app/svg', 8 | scripts: './app/scripts', 9 | static: './app/static', 10 | }, 11 | 12 | dist: { 13 | styles: './dist/assets/styles', 14 | images: './dist/assets/images', 15 | scripts: './dist/assets/scripts', 16 | static: './dist/assets', 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /gulp/tasks/build.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import runSequence from 'run-sequence'; 3 | 4 | gulp.task('build', ['clean'], () => { 5 | runSequence([ 6 | 'markup', 7 | 'styles', 8 | 'scripts:compile', 9 | 'scripts:copy', 10 | 'static', 11 | ], 12 | 'zip' 13 | ); 14 | }); -------------------------------------------------------------------------------- /gulp/tasks/clean.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import del from 'del'; 3 | import vinylPaths from 'vinyl-paths'; 4 | import paths from '../paths'; 5 | 6 | gulp.task('clean', () => { 7 | return gulp 8 | .src(`${paths.baseDist}/*`) 9 | .pipe(vinylPaths(del)); 10 | }); -------------------------------------------------------------------------------- /gulp/tasks/default.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import runSequence from 'run-sequence'; 3 | 4 | gulp.task('default', () => { 5 | runSequence([ 6 | 'markup', 7 | 'styles', 8 | 'scripts:compile', 9 | 'scripts:copy', 10 | 'static', 11 | ], 12 | 'livereload', 13 | 'watch' 14 | ); 15 | }); 16 | -------------------------------------------------------------------------------- /gulp/tasks/livereload.js: -------------------------------------------------------------------------------- 1 | import browserSync from 'browser-sync'; 2 | import gulp from 'gulp'; 3 | import gutil from 'gulp-util'; 4 | import paths from '../paths'; 5 | 6 | gulp.task('livereload', () => { 7 | browserSync.init({ 8 | files: [`${paths.baseDist}/**/*`], 9 | open: !!gutil.env.open, 10 | reloadOnRestart: true, 11 | port: gutil.env.port || 3000, 12 | server: { 13 | baseDir: [ 14 | `${paths.dist.images}`, 15 | `${paths.baseDist}` 16 | ], 17 | directory: false 18 | }, 19 | tunnel: !!gutil.env.tunnel 20 | }) 21 | }); 22 | -------------------------------------------------------------------------------- /gulp/tasks/markup.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import plumber from 'gulp-plumber'; 4 | import jade from 'gulp-jade'; 5 | import inheritance from 'gulp-jade-inheritance'; 6 | import cached from 'gulp-cached'; 7 | import filter from 'gulp-filter'; 8 | import prettify from 'gulp-html-prettify'; 9 | import through from 'through2'; 10 | import errorHandler from '../utils/errorHandler'; 11 | import paths from '../paths'; 12 | 13 | let data = { 14 | jv0: 'javascript:void(0);', 15 | timestamp: +new Date() 16 | }; 17 | 18 | gulp.task('markup', () => { 19 | return gulp 20 | .src(`${paths.baseSrc}/**/*.jade`) 21 | .pipe(plumber({errorHandler: errorHandler})) 22 | .pipe(cached('jade')) 23 | .pipe(gulpif(global.watch, inheritance({basedir: paths.baseSrc}))) 24 | .pipe(filter((file) => /app[\\\/]pages/.test(file.path))) 25 | .pipe(jade({data: data})) 26 | .pipe(prettify({ 27 | brace_style: 'expand', 28 | indent_size: 1, 29 | indent_char: '\t', 30 | indent_inner_html: true, 31 | preserve_newlines: true 32 | })) 33 | .pipe(through.obj(function(file, enc, next) { 34 | const fixedFile = file.clone({contents: false}); 35 | fixedFile.path = file.path.replace(/pages[\/|\\]/g, ''); 36 | this.push(fixedFile); 37 | next(); 38 | })) 39 | .pipe(gulp.dest(paths.baseDist)) 40 | }); -------------------------------------------------------------------------------- /gulp/tasks/scripts.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import uglify from 'gulp-uglify'; 3 | import source from 'vinyl-source-stream'; 4 | import buffer from 'vinyl-buffer'; 5 | import browserify from 'browserify'; 6 | import babel from 'babelify'; 7 | import errorHandler from '../utils/errorHandler'; 8 | import paths from '../paths'; 9 | 10 | gulp.task('scripts:compile', () => { 11 | let bundler = browserify(`${paths.src.scripts}/main.js`, { debug: true }).transform(babel); 12 | return bundler 13 | .bundle() 14 | .on('error', function(err) { console.error(err); this.emit('end'); }) 15 | .pipe(source('build.js')) 16 | .pipe(buffer()) 17 | .pipe(uglify()) 18 | .pipe(gulp.dest(paths.dist.scripts)); 19 | }); 20 | 21 | gulp.task('scripts:copy', () => { 22 | return gulp 23 | .src(`${paths.src.scripts}/vendor/*.js`) 24 | .pipe(uglify()) 25 | .pipe(gulp.dest(`${paths.dist.scripts}/vendor`)); 26 | }); -------------------------------------------------------------------------------- /gulp/tasks/static.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import paths from '../paths'; 3 | 4 | gulp.task('static', () => { 5 | return gulp 6 | .src(`${paths.src.static}/**/*`) 7 | .pipe(gulp.dest(paths.baseDist)); 8 | }); -------------------------------------------------------------------------------- /gulp/tasks/styles.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import plumber from 'gulp-plumber'; 3 | import rupture from 'rupture'; 4 | import stylus from 'gulp-stylus'; 5 | import postcss from 'gulp-postcss'; 6 | import autoprefixer from 'gulp-autoprefixer'; 7 | import svg from 'postcss-svg'; 8 | import flexfixes from 'postcss-flexbugs-fixes'; 9 | import cmq from 'gulp-combine-mq'; 10 | import minifyCss from 'gulp-minify-css'; 11 | import rename from 'gulp-rename'; 12 | import errorHandler from '../utils/errorHandler'; 13 | import paths from '../paths'; 14 | import { browsers } from '../../package.json'; 15 | 16 | gulp.task('styles', () => { 17 | return gulp 18 | .src('*.styl', { 19 | cwd: paths.src.styles, 20 | nonull: true 21 | }) 22 | .pipe(plumber({errorHandler: errorHandler})) 23 | .pipe(stylus({ 24 | errors: true, 25 | use: rupture() 26 | })) 27 | .pipe(autoprefixer( 28 | 'Android >= ' + browsers.android, 29 | 'Chrome >= ' + browsers.chrome, 30 | 'Firefox >= ' + browsers.firefox, 31 | 'Explorer >= ' + browsers.ie, 32 | 'iOS >= ' + browsers.ios, 33 | 'Opera >= ' + browsers.opera, 34 | 'Safari >= ' + browsers.safari 35 | )) 36 | .pipe(postcss([ 37 | svg({ 38 | paths: [paths.src.svg] 39 | }), 40 | flexfixes() 41 | ])) 42 | .pipe(cmq({beautify: false})) 43 | .pipe(minifyCss()) 44 | .pipe(rename({suffix: '.min'})) 45 | .pipe(gulp.dest(paths.dist.styles)) 46 | }); -------------------------------------------------------------------------------- /gulp/tasks/watch.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import watch from 'gulp-watch'; 3 | import runSequence from 'run-sequence'; 4 | import {reload} from 'browser-sync'; 5 | import paths from '../paths'; 6 | import error from '../utils/errorHandler.js' 7 | 8 | gulp.task('watch', () => { 9 | global.watch = true; 10 | 11 | watch(`${paths.baseSrc}/{styles,blocks,svg}/**/*.{styl,svg}`, () => { 12 | runSequence('styles', reload.bind(null, `${paths.dist.styles}/app.min.css`)); 13 | }); 14 | 15 | watch(`${paths.baseSrc}/{layouts,pages,blocks}/**/*.jade`, () => { 16 | runSequence('markup', reload); 17 | }); 18 | 19 | watch(`${paths.src.static}/**/*`, () => { 20 | runSequence('static', reload); 21 | }); 22 | 23 | watch(`${paths.src.scripts}/vendor/*.js`, () => { 24 | runSequence('scripts:copy', reload); 25 | }); 26 | 27 | watch([`${paths.baseSrc}/{scripts,blocks}/**/*.js`, `!${paths.src.scripts}/vendor/*.js`], () => { 28 | runSequence('scripts:compile', reload); 29 | }); 30 | }); -------------------------------------------------------------------------------- /gulp/tasks/zip.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import zip from 'gulp-zip'; 3 | import paths from '../paths'; 4 | 5 | gulp.task('zip', () => { 6 | return gulp 7 | .src([`${paths.baseDist}/**/*`, `!${paths.baseDist}/*.zip`]) 8 | .pipe(zip('dest.zip')) 9 | .pipe(gulp.dest(paths.baseDist)); 10 | }); -------------------------------------------------------------------------------- /gulp/utils/errorHandler.js: -------------------------------------------------------------------------------- 1 | import gutil from 'gulp-util'; 2 | 3 | export default function (error) { 4 | gutil.log([ 5 | (error.name + ' in ' + error.plugin).bold.red, 6 | '', 7 | error.message, 8 | '' 9 | ].join('\n')); 10 | 11 | // Run with `--beep` 12 | if (gutil.env.beep) { 13 | gutil.beep(); 14 | } 15 | 16 | // Keep gulp from hanging on this task 17 | this.emit('end'); 18 | }; -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | require('babel-core/register'); 2 | require('require-dir')('./gulp/tasks', {recurse: true}); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "startanul", 3 | "version": "1.0.0", 4 | "description": "A starter kit for layout building", 5 | "main": "./app/scripts/main.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/andrew--r/startanul.git" 9 | }, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "Andrew Romanov", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "babel-core": "^6.4.0", 17 | "babel-preset-es2015": "^6.3.13", 18 | "babelify": "^7.2.0", 19 | "browser-sync": "^2.11.0", 20 | "browserify": "^13.0.0", 21 | "del": "^2.2.0", 22 | "gulp": "^3.9.0", 23 | "gulp-autoprefixer": "^3.1.0", 24 | "gulp-cached": "^1.1.0", 25 | "gulp-combine-mq": "^0.4.0", 26 | "gulp-filter": "^3.0.1", 27 | "gulp-html-prettify": "0.0.1", 28 | "gulp-if": "^2.0.0", 29 | "gulp-jade": "^1.1.0", 30 | "gulp-jade-inheritance": "^0.5.4", 31 | "gulp-minify-css": "^1.2.3", 32 | "gulp-plumber": "^1.0.1", 33 | "gulp-postcss": "^6.0.1", 34 | "gulp-rename": "^1.2.2", 35 | "gulp-stylus": "^2.2.0", 36 | "gulp-uglify": "^1.5.1", 37 | "gulp-util": "^3.0.7", 38 | "gulp-watch": "^4.3.5", 39 | "gulp-zip": "^3.1.0", 40 | "postcss-flexbugs-fixes": "^2.0.0", 41 | "postcss-inline-svg": "^1.3.0", 42 | "postcss-svg": "^1.0.4", 43 | "require-dir": "^0.3.0", 44 | "run-sequence": "^1.1.5", 45 | "rupture": "^0.6.1", 46 | "through2": "^2.0.1", 47 | "vinyl-buffer": "^1.0.0", 48 | "vinyl-paths": "^2.1.0", 49 | "vinyl-source-stream": "^1.1.0", 50 | "watchify": "^3.7.0" 51 | }, 52 | "browsers": { 53 | "android": 4, 54 | "chrome": 42, 55 | "firefox": 37, 56 | "ie": 10, 57 | "ios": 7, 58 | "opera": 28, 59 | "safari": 7 60 | }, 61 | "dependencies": { 62 | "bemto.jade": "^1.0.2" 63 | } 64 | } 65 | --------------------------------------------------------------------------------