Commit 132610da authored by Dipesh Bathaja's avatar Dipesh Bathaja

Initial Update

root = true
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
insert_final_newline = false
trim_trailing_whitespace = false
# Logs
# Runtime data
# Directory for instrumented libs generated by jscoverage/JSCover
# Coverage directory used by tools like istanbul
# Grunt intermediate storage (
# Compiled binary addons (
# Dependency directory
# Commenting this out is preferred by some people, see
# Users Environment Variables
#IDE configuration files
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": true,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"attr-no-duplication": true,
"title-require": true,
"doctype-html5": true,
"alt-require": true,
"id-class-value": "dash",
"style-disabled": true,
"inline-style-disabled": true,
"id-class-ad-disabled": true
"extends": "stylelint-config-standard",
"rules": {
"block-no-empty": null,
"at-rule-empty-line-before": null,
"rule-non-nested-empty-line-before": null
The MIT License (MIT)
Copyright (c) 2016 Dipesh Batheja
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
# Multi-Device+ SASS Framework
Multi-Device+ SASS Framework is a delicious blend of tasks and build tools poured into [Gulp]( to form a full-featured modern asset pipeline. It can be used as-is as a static site builder, or can be configured and integrated into your own development environment and site or app structure.
Features | Tools Used
------ | -----
**CSS** | [Sass]( ([Libsass]( via [node-sass](, [Autoprefixer](, [CSSNano](, Source Maps, [Rucksack](
**JavaScript** | Folder to keep all your custom Javscript and/or export from Node modules
**HTML** | [Nunjucks](, [gulp-data](
**Images** | Compression with [imagemin](
**Icons** | Auto-generated [SVG Sprites]( and/or [Icon Fonts](
**Fonts** | Folder and `.sass` mixin for including WebFonts
**Live Updating** | [BrowserSync](
**Asset Management** | Framework provides a simple machanism to inject various css and javascript assets on the html page, through a simple JSON configuration file.
**CSS Framework** | [Bootstarp 4] (
**Code Linters** | [HTMLHint] (, [StyleLint] (
## Requirements
### Windows 10
Make sure following tool are installed already in your system, or you can download the installers from the links provided and run a basic setup:
1. Git, GitBash
2. NodeJS
3. Python (v2.7 recommended, v3.x.x is not supported)
- Make sure to select, Add Paython.exe in the PATH during setup.
4. Visual Studio 2015 - Community Edition
- Select Custom Install
- Select Visual C++ in programming languages
### Mac OS X
1. Git (already installed on Mac OS X)
2. Python (v2.7 recommended, v3.x.x is not supported) (already installed on Mac OS X)
3. NodeJS
4. Xcode
- You also need to install the Command Line Tools via Xcode. You can find this under the menu Xcode -> Preferences -> Downloads. This step will install gcc and the related toolchain containing make
### All Platforms
Install global dependencies with following command through your terminal window once all above tools are installed.
npm install --global gulp-cli && npm install --global typings && npm install --global typescript
## Getting started
Open Terminal window to run following commands:
#### Clone repository
git clone new-project
cd new-project
#### Clear out `git` data
If you plan on using this framework to start a new project, be sure and clear out the `git` data to start a fresh history:
rm -rf .git && git init
git add --all
git commit -m "Initialized with Multi Device+ SASS Framework"
#### Install node dependencies
npm install
## Usage
### Run server in development mode:
npm start
Aliases: `npm run gulp`
This is where the magic happens. The perfect front-end workflow. This runs the default gulp task, which starts compiling, watching, and live updating all our files as we change them. BrowserSync will start a server on port 3000, or do whatever you've configured it to do. You'll be able to see live changes in all connected browsers. Don't forget about the additional BrowserSync tools available on port 3001!
All files will compile in development mode (uncompressed with source maps). [BrowserSync]( will serve up files to `localhost:3000` and will stream live changes to the code and assets to all connected browsers. Don't forget about the additional BrowserSync tools available on `localhost:3001`!
### Build files in development mode:
npm run build
This will just compile the files in development mode in source folder to specified distribution folder. This will not run a live server.
## Configuration
Why run this as an npm script? NPM scripts add ./node_modules/bin to the path when run, using the packages version installed with this project, rather than a globally installed ones. Never `npm install -g` and get into mis-matched version issues again. These scripts are defined in the `scripts` property of `package.json`.
All commands in the package.json `scripts` work this way. The `gulp` command runs the `default` task, defined in `tools/tasks/start.ts`.
Directory and top level settings are conveniently exposed in `tools/config.ts`. Use this file to update paths to match the directory structure of your project, and to adjust task options.
Not all configuration is exposed here. For advanced task configuration, you can always edit the tasks themselves in `tools/tasks`.
## Asset Task Details
A `` with details about each asset task are available in their respective folders in the `src` directory:
- [JavaScript](src/javascripts)
- [Stylesheets](src/stylesheets)
- [HTML](src/html)
- [Fonts](src/fonts)
- [Images](src/images)
- [Icon Font](src/icons#iconfont-task)
- [SVG Sprite](src/icons#svg-sprite-task)
- [Static Files (favicons, etc.)](src/static)
Rather than manage one giant configuration file responsible
for creating multiple tasks, each task has been broken out into
its own file in tools/tasks. Any files in that directory get
automatically required below.
To add a new task, simply add a new task file that directory.
tools/tasks/default.js specifies the default set of tasks to run
when you run `gulp`.
import { TASKS_DIR } from "./tools/config";
import * as requireDir from "require-dir";
// Require all tasks in tools/tasks, including subfolders
requireDir(TASKS_DIR, { recurse: false });
"name": "frontend-starter",
"version": "1.0.0",
"scripts": {
"start": "gulp --color",
"build": "gulp clean && gulp build",
"postinstall": "typings install && npm prune"
"author": "Dipesh Batheja",
"license": "MIT",
"description": "Frontend Starter Kit",
"devDependencies": {
"autoprefixer": "^6.3.6",
"browser-sync": "^2.12.10",
"chalk": "^1.1.3",
"cssnano": "^3.7.0",
"decache": "^4.1.0",
"del": "^2.2.0",
"eslint": "^2.11.1",
"fs": "0.0.2",
"gulp": "^3.9.1",
"gulp-changed": "^1.3.0",
"gulp-data": "^1.2.1",
"gulp-htmlhint": "^0.3.1",
"gulp-htmlhint-html-reporter": "^1.0.1",
"gulp-if": "^2.0.1",
"gulp-imagemin": "^3.0.1",
"gulp-inject": "^4.1.0",
"gulp-load-plugins": "^1.2.4",
"gulp-notify": "^2.2.0",
"gulp-nunjucks-render": "^2.0.0",
"gulp-postcss": "^6.1.1",
"gulp-prettify": "^0.5.0",
"gulp-rucksack": "^0.1.3",
"gulp-sass": "^2.3.1",
"gulp-sourcemaps": "^1.6.0",
"gulp-svgstore": "^6.0.0",
"gulp-typescript": "^2.13.6",
"gulp-util": "^3.0.7",
"gulp-watch": "^4.3.6",
"htmlhint": "^0.9.13",
"htmlhint-stylish": "^1.0.3",
"jsonfile": "^2.3.1",
"lodash": "^4.13.1",
"merge-stream": "^1.0.0",
"postcss-object-fit-images": "^1.1.2",
"require-dir": "^0.3.0",
"run-sequence": "^1.2.1",
"stylelint": "^6.5.1",
"stylelint-config-standard": "^8.0.0",
"ts-node": "^0.7.3",
"tslint": "^3.10.2",
"typescript": "^1.8.10",
"typings": "^1.0.4",
"yargs": "^4.7.1"
"dependencies": {
"bootstrap": "^4.0.0-alpha.2",
"jquery": "^2.2.4",
"lt-ie-9": "^0.1.0",
"tether": "^1.3.2"
"project_name": "ProjectTitle",
"assets": [
{ "src": "src/client/stylesheets/bootstrap.scss", "inject": "stylesheets" },
{ "src": "src/client/stylesheets/iconfont.scss", "inject": false },
{ "src": "src/client/stylesheets/main.scss", "inject": "stylesheets" },
{ "src": "src/client/javascript/head.core.js", "inject": "head" },
{ "src": "node_modules/lt-ie-9/lt-ie-9.js", "inject": "lt-ie-9" },
{ "src": "node_modules/jquery/dist/jquery.js", "inject": "footer" },
{ "src": "node_modules/tether/dist/js/tether.js", "inject": "footer" },
{ "src": "node_modules/bootstrap/dist/js/bootstrap.js", "inject": "footer" },
{ "src": "src/client/javascript/main.js", "inject": "footer" }
# Font Assets
If you are providing web font files, this is the place to put them. The fonts task will copy them over to the destination specified in `tools/config.ts`.
### Gulp Tasks
All this task does is copy fonts from `./src/fonts` to `./public/fonts`.
### Mixins
A sass `font-face` mixin is included in `./src/stylesheets/mixins/_font-face.scss`.
Include mixin in your css font file (example: `./src/stylesheets/fonts/_open-sans.scss`).
@include font-face("Open Sans", "fonts/open-sans-regular");
Rendered as CSS:
@font-face {
font-family: "Open Sans";
src: url('open-sans-regular.eot');
src: url('open-sans-regular.eot?#iefix') format('embedded-opentype'),
url('open-sans-regular.woff') format('woff'),
url('open-sans-regular.ttf') format('truetype'),
url('open-sans-regular.svg#Open Sans') format('svg');
font-weight: normal;
font-style: normal;
Or Create a font face rule that applies to bold and italic text.
@include font-face("Open Sans", "fonts/open-sans-bold-italic", bold, italic);
Rendered as CSS:
@font-face {
font-family: "Open Sans";
src: url('open-sans-regular.eot');
src: url('open-sans-bold-italic.eot?#iefix') format('embedded-opentype'),
url('open-sans-bold-italic.woff') format('woff'),
url('open-sans-bold-italic.ttf') format('truetype'),
url('open-sans-bold-italic.svg#Open Sans') format('svg');
font-weight: bold;
font-style: italic;
\ No newline at end of file
# HTML Assets
If you are using gulp-starter with another platform that handles markup, delete this folder and the `tasks.html` config in `gulpfile.js/config.json`, and don't forget to [configure BrowserSync to watch your platform's template files]( for changes!
If you are using gulp-starter as a standalone static site builder, this is where your markup goes. I've provided a few [Nunjucks]( folders and files to get you started:
- **layouts:** A basic Nunjucks layout file
- **macros:** Contains a helpers file.
- **shared:** A folder to put shared partials.
- **index.html:** Hello world! Uses `layouts/default.html`.
### Tasks and Files
Robust templating with [Nunjucks]( Nunjucks is nearly identical in syntax to Twig (PHP), and replaces Swig (and Twig-like js templating language), which is no longer maintained.
A global config file is set up at [src/config.json](src/config.json), is read in by the `html` task, and exposes the properties to your html templates.
This config file also allows you the add assets like Stylesheets and Javascript that are injected in various places in HTML using (gulp-inject) [].
{ "src": "node_modules/jquery/dist/jquery.js", "inject": "footer" }
In above example, `src` specify the path of the Jquery library file from the project root folder. `inject` specify the location in HTML file where this Javascript file will be injected.
{% set html_class = "" %}
{% set body_class = "" %}
{% set page_name = "Home" %}
{% extends 'layouts/default.html' %}
{% block container %}
<h1>Hello World</h1>
{% endblock %}
<!doctype html>
<html class="{{ html_class }}">
<!-- Meta Tags -->
{% block meta %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% endblock %}
<!-- Page Title -->
<title>{% block title %}{{ page_name }} | {{ project_name }}{% endblock %}</title>
<!-- Favicons -->
<!-- Generate using -->
<!-- Stylesheets -->
{% block stylesheets %}
<!-- stylesheets:css -->
<!-- endinject -->
{% endblock %}
<!-- Javascript -->
{% block head_js %}
<!-- head:js -->
<!-- endinject -->
<!--[if lt IE 9]>
<!-- lt-ie-9:js -->
<!-- endinject -->
<!-- [endif] -->
{% endblock %}
<body class="{{ body_class }}">
{% block before_container %}{% endblock %}
{% block container%}{% endblock %}
{% block after_container %}
<!-- Footer Javascript -->
<!-- footer:js -->
<!-- endinject -->
{% endblock %}
# Icon Assets
Drop SVG files here to automatically compile and recompile either an SVG sprite or an Icon Font containing all your icons. While you could use both methods at the same time, it probably makes sense to only use one. My personal preference is SVG sprites. Which ever method you choose, **be sure to disable or remove the config for the method you're not using** in `gulpfile.js/config.json`.
If you don't plan using SVG sprites or an Icon Font, you may delete this folder and the associated task config in `gulpfile.js/config.json`.
## Tasks and Files
### SVG Sprite Task
Generates an SVG Sprite! You can either include the created SVG directly on the page and reference the icon by id like this:
<svg viewBox="0 0 1 1"><use xlink:href='#my-icon' /></use></svg>
or reference the image remotely.
<svg viewBox="0 0 1 1"><use xlink:href='images/spritesheets/sprites.svg#my-icon' /></use></svg>
If you refernce the sprite remotely, be sure to include to ensure external loading works on Internet Explorer.
I've included a helper to generate the required svg markup in `src/html/macros/helpers.html`, so you can just do:
{{ sprite('my-icon') }}
Which spits out:
<span class='sprite -my-icon'>
<svg viewBox="0 0 1 1"><use xlink:href='images/spritesheets/sprites.svg#my-icon' /></use></svg>
This particular setup allows styling 2 different colors from your css. You can have unlimited colors hard coded into your svg.
In the following example, the first path will be `red`, the second will be `white`, and the third will be `blue`. Paths **without a fill attribute** will inherit the `fill` property from css. Paths with **fill="currentColor"** will inherit the current css `color` value, and hard-coded fills will not be overwritten, since inline styles trump css values.
fill: red
color: white
<svg xmlns="">
<path d="..."/>
<path fill="currentColor" d="..."/>
<path fill="blue" d="..."/>
I recommend setting up your SVGs on a 500 x 500 canvas, centering your artwork, and expanding/combining any shapes of the same color. This last step is important. [Read more on SVG optimization here!](
### IconFont Task
SVGs added to `src/icons` will be automatically compiled into an iconFont, and output to `./public/fonts`. At the same time, a `.sass` file will be output to `src/stylesheets/generated/_icons.sass`. This file contains mixins and classes based on the svg filename. If you want to edit the template that generates this file, it's at `gulpfile.js/tasks/iconFont/template.sass`. If you have the option, I'd recommend using SVG sprites (see below) over this method for icons.
##### Usage:
With generated classes:
<span class="icon -twitter"></span>
With mixins:
.lil-birdy-guy {
@include icon--twitter;
<span class="lil-birdy-guy"></span>
*Don't forget about accessibility!*
<span aria-label="Twitter" class="icon -twitter"></span>
<!-- or -->
<div class="icon -twitter"><span class="screen-reader">Twitter</span></div>
# JavaScript Assets
All the custom JavaScript you add here will be copied over to destination folder specified in `tools/config.ts` during build process.
Note that you still need to include entries for each Javascript file you want to inject in your HTML files in `src/config.json`.
### Tasks and Files
///#source 1 1 /src/1.0.0/core.js
/*! head.core - v1.0.2 */
* HeadJS The only script in your <HEAD>
* Author Tero Piirainen (tipiirai)
* Maintainer Robert Hoffmann (itechnology)
* License MIT /
* WebSite
(function(win, undefined) {
"use strict";
// gt, gte, lt, lte, eq breakpoints would have been more simple to write as ['gt','gte','lt','lte','eq']
// but then we would have had to loop over the collection on each resize() event,
// a simple object with a direct access to true/false is therefore much more efficient
var doc = win.document,
nav = win.navigator,
loc = win.location,
html = doc.documentElement,
klass = [],
conf = {
screens : [240, 320, 480, 640, 768, 800, 1024, 1280, 1440, 1680, 1920],
screensCss: { "gt": true, "gte": false, "lt": true, "lte": false, "eq": false },
browsers : [
{ ie: { min: 6, max: 11 } }
//,{ chrome : { min: 8, max: 33 } }
//,{ ff : { min: 3, max: 26 } }
//,{ ios : { min: 3, max: 7 } }
//,{ android: { min: 2, max: 4 } }
//,{ webkit : { min: 9, max: 12 } }
//,{ opera : { min: 9, max: 12 } }
browserCss: { "gt": true, "gte": false, "lt": true, "lte": false, "eq": true },
html5 : true,
page : "-page",
section : "-section",
head : "head"
if (win.head_conf) {
for (var item in win.head_conf) {
if (win.head_conf[item] !== undefined) {
conf[item] = win.head_conf[item];
function pushClass(name) {
klass[klass.length] = name;
function removeClass(name) {
// need to test for both space and no space
var re = new RegExp(" ?\\b" + name + "\\b");
html.className = html.className.replace(re, "");
function each(arr, fn) {
for (var i = 0, l = arr.length; i < l; i++) {, arr[i], i);
// API
var api = win[conf.head] = function() {
api.ready.apply(null, arguments);
api.feature = function(key, enabled, queue) {
// internal: apply all classes
if (!key) {
html.className += " " + klass.join(" ");
klass = [];
return api;
if ( === "[object Function]") {
enabled =;
pushClass((enabled ? "" : "no-") + key);
api[key] = !!enabled;
// apply class to HTML element
if (!queue) {
removeClass("no-" + key);
return api;
// no queue here, so we can remove any eventual pre-existing no-js class
api.feature("js", true);
// browser type & version
var ua = nav.userAgent.toLowerCase(),
mobile = /mobile|android|kindle|silk|midp|phone|(windows .+arm|touch)/.test(ua);
// useful for enabling/disabling feature (we can consider a desktop navigator to have more cpu/gpu power)
api.feature("mobile" , mobile , true);
api.feature("desktop", !mobile, true);
ua = /(chrome|firefox)[ \/]([\w.]+)/.exec(ua) || // Chrome & Firefox
/(iphone|ipad|ipod)(?:.*version)?[ \/]([\w.]+)/.exec(ua) || // Mobile IOS
/(android)(?:.*version)?[ \/]([\w.]+)/.exec(ua) || // Mobile Webkit
/(webkit|opera)(?:.*version)?[ \/]([\w.]+)/.exec(ua) || // Safari & Opera
/(msie) ([\w.]+)/.exec(ua) ||
/(trident).+rv:(\w.)+/.exec(ua) || [];
var browser = ua[1],
version = parseFloat(ua[2]);
switch (browser) {
case "msie":
case "trident":
browser = "ie";
version = doc.documentMode || version;
case "firefox":
browser = "ff";
case "ipod":
case "ipad":
case "iphone":
browser = "ios";