Merge branch 'master' of github.com:ungleich/dynamicweb

This commit is contained in:
Nico Schottelius 2016-05-14 22:30:05 +02:00
commit 4f40fd1efa
695 changed files with 94995 additions and 5257 deletions

5
.gitignore vendored
View file

@ -2,7 +2,6 @@ db.sqlite3
*.pyc
*.DS_Store
build/
dist/
*.egg_info
#editors && utilites.
*.swp
@ -12,7 +11,7 @@ __pycache__/
#django
local_settings.py
media/*
media/
!media/keep
/CACHE/
/static/
@ -30,6 +29,8 @@ ungleich.db
secret-key
*.psd
.idea/
.env

68
INSTALLATION.rst Normal file
View file

@ -0,0 +1,68 @@
Dynamicweb
----------
Installation for dynamicweb
=======
Requirements
============
* Python 3.5+
Install
=======
The quick way:
``pip install -r requirements.txt``
Next find the dump.db file on stagging server. Path for the file is under the base application folder.
Install the postgresql server and import the database::
``psql -d app < dump.db``
**No migration is needed after a clean install, and You are ready to start developing.**
Development
===========
Project is separated in master branch and development branch, and feature branches.
Master branch is currently used on `Digital Glarus <https://digitalglarus.ungleich.ch/en-us/digitalglarus/>`_ and `Ungleich blog <https://digitalglarus.ungleich.ch/en-us/blog/>`_.
If You are starting to create a new feature fork the github `repo <https://github.com/ungleich/dynamicweb>`_ and branch the development branch.
After You have complited the task create a pull request and ask someone to review the code from other developers.
**Cheat sheet for branching and forking**:
*branching*
``git branch feature_name && git checkout feature_name``
*fetching upstream(should be done everytime before development is started)*
``git fetch upstream && git merge upstream/feature_name``
`read more about getting code from upstream here <https://help.github.com/articles/syncing-a-fork/>`_
*merging your branch*
(**IMPORTANT**)
Before You make a pull request from Your forked branch to the ungleich make sure You did merge and resolve any conflicts You may find and that the application is running bug free.
Also You can run
``./manage test``
To merge upstream branch run this git commands.
``git fetch upstream``
``git checkout your_feature_branch``
``git merge remotes/upstream/develop``

View file

@ -13,10 +13,4 @@ Website for ungleich GmbH
- /hosting/rubyonrails/
- /hosting/nodejs/
--
- feedback app
- below ungleich?
- no
- redirect back to // render other url?
- /feedback
<form action="{% url 'hosting:index' %}" method="post" role="form" class="form-inline">

View file

@ -8,4 +8,4 @@
<li>{{ message.received_date }}
</ul>
<p><a href="{% url 'digitalglarus:index' %}">Back to Main</a>
<p><a href="{% url 'digitalglarus:home' %}">Back to Main</a>

View file

@ -0,0 +1,110 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Calendar</title>
<link rel="stylesheet" href="stylesheet.css">
</head>
<body>
<div class="container">
<div class="calendar">
<header>
<h2>September</h2>
<a class="btn-prev fontawesome-angle-left" href="#"></a>
<a class="btn-next fontawesome-angle-right" href="#"></a>
</header>
<table>
<thead>
<tr>
<td>Mo</td>
<td>Tu</td>
<td>We</td>
<td>Th</td>
<td>Fr</td>
<td>Sa</td>
<td>Su</td>
</tr>
</thead>
<tbody>
<tr>
<td class="prev-month">26</td>
<td class="prev-month">27</td>
<td class="prev-month">28</td>
<td class="prev-month">29</td>
<td class="prev-month">30</td>
<td class="prev-month">31</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>9</td>
<td class="event">10</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
<td>20</td>
<td class="event">21</td>
<td>22</td>
</tr>
<tr>
<td class="current-day event">23</td>
<td>24</td>
<td>25</td>
<td>26</td>
<td>27</td>
<td>28</td>
<td>29</td>
</tr>
<tr>
<td>30</td>
<td class="next-month">1</td>
<td class="next-month">2</td>
<td class="next-month">3</td>
<td class="next-month">4</td>
<td class="next-month">5</td>
<td class="next-month">6</td>
</tr>
</tbody>
</table>
</div> <!-- end calendar -->
</div> <!-- end container -->
</body>
</html>

View file

@ -0,0 +1,107 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Calendar</title>
<link rel="stylesheet" href="stylesheet.css">
</head>
<body>
<div class="container">
<div class="calendar">
<header>
<a class="btn-prev fontawesome-angle-left" href="#"></a>
<span id="monthtitle">September</span>
<a class="btn-next fontawesome-angle-right" href="#"></a>
<table>
<thead>
<tr>
<td>Mo</td>
<td>Tu</td>
<td>We</td>
<td>Th</td>
<td>Fr</td>
<td>Sa</td>
<td>Su</td>
</tr>
</thead>
<tbody>
<tr>
<td class="prev-month">26</td>
<td class="prev-month">27</td>
<td class="prev-month">28</td>
<td class="prev-month">29</td>
<td class="prev-month">30</td>
<td class="prev-month">31</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>9</td>
<td class="event">10</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
<td>20</td>
<td class="event">21</td>
<td>22</td>
</tr>
<tr>
<td class="current-day event">23</td>
<td>24</td>
<td>25</td>
<td>26</td>
<td>27</td>
<td>28</td>
<td>29</td>
</tr>
<tr>
<td>30</td>
<td class="next-month">1</td>
<td class="next-month">2</td>
<td class="next-month">3</td>
<td class="next-month">4</td>
<td class="next-month">5</td>
<td class="next-month">6</td>
</tr>
</tbody>
</table>
</div> <!-- end calendar -->
</div> <!-- end container -->
</body>
</html>

View file

@ -0,0 +1,160 @@
@charset "utf-8";
/* CSS Document */
/* ---------- FONTAWESOME ---------- */
/* ---------- http://fortawesome.github.com/Font-Awesome/ ---------- */
/* ---------- http://weloveiconfonts.com/ ---------- */
@import url(http://weloveiconfonts.com/api/?family=fontawesome);
*[class*="fontawesome-"]:before {
font-family: 'FontAwesome', sans-serif;
}
/* ---------- GENERAL ---------- */
body {
background: #f9f9f9;
color: #0e171c;
font: 300 100%/1em 'Lato', sans-serif;
margin: 0;
}
a {
text-decoration: none;
}
/*Month size*/
#monthtitle {
font-size: 1.2em;
line-height: 1.25em;
margin: .25em 0;
font-weight: 600;
}
h3 {
font-size: 1.5em;
line-height: 1em;
margin: .33em 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
margin:auto;
}
.container {
height: 358px;
left: 50%;
margin: -255px 0 0 -245px;
position: absolute;
top: 50%;
width: 340px;
}
/* ---------- CALENDAR ---------- */
.calendar {
text-align: center;
}
.calendar header {
position: relative;
}
.calendar #monthtitle {
text-transform: uppercase;
color: #1A6687;
}
/*Title*/
.calendar thead {
font-weight: 500;
/*text-transform: uppercase;*/
color: #8BC4C9;
/*margin-bottom:1px;*/
}
/*Body text*/
.calendar tbody {
color: #7c8a95;
}
/*select date*/
.calendar tbody td:hover {
background: #347D80;
color: #f9f9f9;
/*border: .1px solid #8BC4C9;*/
/*border-radius: 50%;*/
}
.calendar thead>tr>td{
border-top:hidden;
border-left:hidden;
border-right: hidden;
}
.calendar td {
border: .1px solid #cbd1d2;
/*border-radius: 50%;*/
display: inline-block;
height: 2.5em;
line-height: 2.5em;
text-align: center;
width: 2.5em;
}
.calendar .prev-month,
.calendar .next-month {
/*border: .1px solid #cbd1d2;*/
color: #cbd1d2;
}
.calendar .prev-month:hover,
.calendar .next-month:hover {
border: .5px solid #cbd1d2;
background: #cbd1d2;
color: #f9f9f9;
}
/*Today*/
.current-day {
color: #8BC4C9;
/*background-color: #8BC4C9;*/
}
/*Next,Prev month*/
.btn-prev,
.btn-next {
border: 1px solid transparent;
color: #8BC4C9;
font-size: 1.5em;
padding: 1em;
/*height: .7em;*/
/*line-height: .3em;*/
/*margin: auto;*/
/*position: absolute;*/
/*top: .1em;*/
/*width: 25em;*/
}
.btn-prev:hover,
.btn-next:hover {
background: none;
color: #1A6687;
}
.btn-prev {
left: 6em;
}
.btn-next {
right: 6em;
}

View file

@ -0,0 +1,165 @@
@charset "utf-8";
/* CSS Document */
/* ---------- FONTAWESOME ---------- */
/* ---------- http://fortawesome.github.com/Font-Awesome/ ---------- */
/* ---------- http://weloveiconfonts.com/ ---------- */
@import url(http://weloveiconfonts.com/api/?family=fontawesome);
*[class*="fontawesome-"]:before {
font-family: 'FontAwesome', sans-serif;
}
/* ---------- GENERAL ---------- */
body {
background: #f9f9f9;
color: #0e171c;
font: 300 100%/1.5em 'Lato', sans-serif;
margin: 0;
}
a {
text-decoration: none;
}
/*Month size*/
h2 {
font-size: 1.5em;
line-height: 1.25em;
margin: .25em 0;
}
h3 {
font-size: 1.5em;
line-height: 1em;
margin: .33em 0;
}
table {
/*border-collapse: collapse;*/
border-spacing: 0;
margin:auto;
}
.container {
height: 558px;
left: 50%;
margin: -255px 0 0 -245px;
position: absolute;
top: 50%;
width: 540px;
}
/* ---------- CALENDAR ---------- */
.calendar {
text-align: center;
}
.calendar header {
position: relative;
}
.calendar h2 {
text-transform: uppercase;
color: #1A6687;
}
/*Title*/
.calendar thead {
font-weight: 600;
text-transform: uppercase;
color: #8BC4C9;
}
/*Body text*/
.calendar tbody {
color: #7c8a95;
}
/*select date*/
.calendar tbody td:hover {
border: .5px solid #8BC4C9;
-webkit-border: .5px solid none;
border-radius: 50%;
}
.calendar td {
border: .5px solid transparent;
border-radius: 50%;
display: inline-block;
height: 2.5em;
line-height: 2.5em;
text-align: center;
width: 2.5em;
}
.calendar .prev-month,
.calendar .next-month {
color: #cbd1d2;
}
.calendar .prev-month:hover,
.calendar .next-month:hover {
border: .5px solid #cbd1d2;
}
/*Today*/
.current-day {
background: #8BC4C9;
color: #f9f9f9;
}
.event {
cursor: pointer;
position: relative;
}
/*Little dot*/
.event:after {
background: #8BC4C9;
border-radius: 50%;
bottom: .35em;
display: block;
content: '';
height: .35em;
left: 50%;
margin: -.25em 0 0 -.25em ;
position: absolute;
width: .35em;
}
.event.current-day:after {
background: #f9f9f9;
}
/*Next,Prev month*/
.btn-prev,
.btn-next {
border: 1px solid transparent;
color: #8BC4C9;
height: 2em;
font-size: .75em;
line-height: 2em;
margin: auto;
position: absolute;
top: .3em;
width: 10em;
}
.btn-prev:hover,
.btn-next:hover {
background: none;
color: #1A6687;
}
.btn-prev {
left: 6em;
}
.btn-next {
right: 6em;
}

View file

@ -1,5 +1,6 @@
from django.contrib import admin
from .models import Message, Supporter, DGGallery, DGPicture
from .models import Supporter, DGGallery, DGPicture
from utils.models import ContactMessage
#
class DGPictureInline(admin.StackedInline):
model = DGPicture
@ -8,5 +9,5 @@ class DGGalleryAdmin(admin.ModelAdmin):
inlines = [DGPictureInline]
admin.site.register(DGGallery, DGGalleryAdmin)
admin.site.register(Message)
admin.site.register(ContactMessage)
admin.site.register(Supporter)

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-04-09 12:46-0500\n"
"POT-Creation-Date: 2016-04-15 22:24-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -26,22 +26,6 @@ msgstr ""
msgid "Digital Glarus Supporters"
msgstr ""
#: forms.py:21
msgid "Name"
msgstr "Name"
#: forms.py:22
msgid "Email"
msgstr "Email"
#: forms.py:23
msgid "Phone number"
msgstr "Telefon"
#: forms.py:24
msgid "Message"
msgstr "Nachricht"
#: templates/glarus_blog/includes/blog_item.html:32
msgid "read more"
msgstr ""
@ -79,17 +63,40 @@ msgid "Change to language:"
msgstr ""
#: urls.py:8
msgid "home/?$"
msgstr "haus/?$"
#: urls.py:9
msgid "about/?$"
msgstr "etwa/?$"
#: urls.py:10
msgid "contact/?$"
msgstr "kontakt/?$"
#: urls.py:9
#: urls.py:11
msgid "supporters/?$"
msgstr "befurworter/?$"
#: urls.py:10
#: urls.py:12
msgid "support-us/?$"
msgstr ""
#: views.py:23
msgid "Message Successfully Sent"
msgstr ""
#~ msgid "index/?$"
#~ msgstr "index/?$"
#~ msgid "Name"
#~ msgstr "Name"
#~ msgid "Email"
#~ msgstr "Email"
#~ msgid "Phone number"
#~ msgstr "Telefon"
#~ msgid "Message"
#~ msgstr "Nachricht"

View file

View file

@ -0,0 +1,14 @@
from django.core.management.base import BaseCommand
from django.conf import settings
import stripe
stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
class Command(BaseCommand):
help = "Record payment plans for Digital Glarus on stripe"
def handle(self, *args, **options):
print("Available plans:")
for plan in stripe.Plan.all():
print(plan)

View file

@ -0,0 +1,33 @@
from django.core.management.base import BaseCommand
from django.conf import settings
import stripe
stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
PAYMENT_PLANS = [
('spontaneous', {'amount': 3500,
'interval': "month",
'name': "The Spontaneous",
'currency': "chf",
'id': "spontaneus"
}),
('committed', {
'amount':36000,
'interval':'year',
'name':'The Committed',
'currency':'chf',
'id':'committed'
})
]
class Command(BaseCommand):
help = "Record payment plans for Digital Glarus on stripe"
def handle(self, *args, **options):
for payment_plan, data in PAYMENT_PLANS:
try:
res = stripe.Plan.create(**data)
except stripe.InvalidRequestError as e:
print(e)

View file

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-04-10 17:10
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('digitalglarus', '0005_auto_20160407_0519'),
]
operations = [
migrations.DeleteModel(
name='Message',
),
]

View file

@ -1,23 +1,13 @@
from django.db import models
from cms.models import CMSPlugin
from filer.fields.image import FilerImageField
class Message(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
phone_number = models.CharField(max_length=200)
message = models.TextField()
received_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "%s - %s - %s" % (self.name, self.email, self.received_date)
from django.core.urlresolvers import reverse
class Supporter(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
def __str__(self):
return "%s" % (self.name)

Binary file not shown.

View file

@ -322,6 +322,8 @@ footer .copyright {
.floating-label-form-group-with-focus label {
color: #0085a1;
}
form .row:first-child .floating-label-form-group {
border-top: 1px solid #eeeeee;
}

View file

@ -0,0 +1,45 @@
{
"name": "bootstrap",
"description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
"keywords": [
"css",
"js",
"less",
"mobile-first",
"responsive",
"front-end",
"framework",
"web"
],
"homepage": "http://getbootstrap.com",
"license": "MIT",
"moduleType": "globals",
"main": [
"less/bootstrap.less",
"dist/js/bootstrap.js"
],
"ignore": [
"/.*",
"_config.yml",
"CNAME",
"composer.json",
"CONTRIBUTING.md",
"docs",
"js/tests",
"test-infra"
],
"dependencies": {
"jquery": "1.9.1 - 2"
},
"version": "3.3.6",
"_release": "3.3.6",
"_resolution": {
"type": "version",
"tag": "v3.3.6",
"commit": "81df608a40bf0629a1dc08e584849bb1e43e0b7a"
},
"_source": "https://github.com/twbs/bootstrap.git",
"_target": "^3.3.6",
"_originalSource": "bootstrap",
"_direct": true
}

View file

@ -0,0 +1,5 @@
Bootstrap uses [GitHub's Releases feature](https://github.com/blog/1547-release-your-software) for its changelogs.
See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap.
Release announcement posts on [the official Bootstrap blog](http://blog.getbootstrap.com) contain summaries of the most noteworthy changes made in each release.

View file

@ -0,0 +1,533 @@
/*!
* Bootstrap's Gruntfile
* http://getbootstrap.com
* Copyright 2013-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
module.exports = function (grunt) {
'use strict';
// Force use of Unix newlines
grunt.util.linefeed = '\n';
RegExp.quote = function (string) {
return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
};
var fs = require('fs');
var path = require('path');
var npmShrinkwrap = require('npm-shrinkwrap');
var generateGlyphiconsData = require('./grunt/bs-glyphicons-data-generator.js');
var BsLessdocParser = require('./grunt/bs-lessdoc-parser.js');
var getLessVarsData = function () {
var filePath = path.join(__dirname, 'less/variables.less');
var fileContent = fs.readFileSync(filePath, { encoding: 'utf8' });
var parser = new BsLessdocParser(fileContent);
return { sections: parser.parseFile() };
};
var generateRawFiles = require('./grunt/bs-raw-files-generator.js');
var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js');
var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' });
Object.keys(configBridge.paths).forEach(function (key) {
configBridge.paths[key].forEach(function (val, i, arr) {
arr[i] = path.join('./docs/assets', val);
});
});
// Project configuration.
grunt.initConfig({
// Metadata.
pkg: grunt.file.readJSON('package.json'),
banner: '/*!\n' +
' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
' * Licensed under the <%= pkg.license %> license\n' +
' */\n',
jqueryCheck: configBridge.config.jqueryCheck.join('\n'),
jqueryVersionCheck: configBridge.config.jqueryVersionCheck.join('\n'),
// Task configuration.
clean: {
dist: 'dist',
docs: 'docs/dist'
},
jshint: {
options: {
jshintrc: 'js/.jshintrc'
},
grunt: {
options: {
jshintrc: 'grunt/.jshintrc'
},
src: ['Gruntfile.js', 'package.js', 'grunt/*.js']
},
core: {
src: 'js/*.js'
},
test: {
options: {
jshintrc: 'js/tests/unit/.jshintrc'
},
src: 'js/tests/unit/*.js'
},
assets: {
src: ['docs/assets/js/src/*.js', 'docs/assets/js/*.js', '!docs/assets/js/*.min.js']
}
},
jscs: {
options: {
config: 'js/.jscsrc'
},
grunt: {
src: '<%= jshint.grunt.src %>'
},
core: {
src: '<%= jshint.core.src %>'
},
test: {
src: '<%= jshint.test.src %>'
},
assets: {
options: {
requireCamelCaseOrUpperCaseIdentifiers: null
},
src: '<%= jshint.assets.src %>'
}
},
concat: {
options: {
banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>',
stripBanners: false
},
bootstrap: {
src: [
'js/transition.js',
'js/alert.js',
'js/button.js',
'js/carousel.js',
'js/collapse.js',
'js/dropdown.js',
'js/modal.js',
'js/tooltip.js',
'js/popover.js',
'js/scrollspy.js',
'js/tab.js',
'js/affix.js'
],
dest: 'dist/js/<%= pkg.name %>.js'
}
},
uglify: {
options: {
compress: {
warnings: false
},
mangle: true,
preserveComments: 'some'
},
core: {
src: '<%= concat.bootstrap.dest %>',
dest: 'dist/js/<%= pkg.name %>.min.js'
},
customize: {
src: configBridge.paths.customizerJs,
dest: 'docs/assets/js/customize.min.js'
},
docsJs: {
src: configBridge.paths.docsJs,
dest: 'docs/assets/js/docs.min.js'
}
},
qunit: {
options: {
inject: 'js/tests/unit/phantom.js'
},
files: 'js/tests/index.html'
},
less: {
compileCore: {
options: {
strictMath: true,
sourceMap: true,
outputSourceFiles: true,
sourceMapURL: '<%= pkg.name %>.css.map',
sourceMapFilename: 'dist/css/<%= pkg.name %>.css.map'
},
src: 'less/bootstrap.less',
dest: 'dist/css/<%= pkg.name %>.css'
},
compileTheme: {
options: {
strictMath: true,
sourceMap: true,
outputSourceFiles: true,
sourceMapURL: '<%= pkg.name %>-theme.css.map',
sourceMapFilename: 'dist/css/<%= pkg.name %>-theme.css.map'
},
src: 'less/theme.less',
dest: 'dist/css/<%= pkg.name %>-theme.css'
}
},
autoprefixer: {
options: {
browsers: configBridge.config.autoprefixerBrowsers
},
core: {
options: {
map: true
},
src: 'dist/css/<%= pkg.name %>.css'
},
theme: {
options: {
map: true
},
src: 'dist/css/<%= pkg.name %>-theme.css'
},
docs: {
src: ['docs/assets/css/src/docs.css']
},
examples: {
expand: true,
cwd: 'docs/examples/',
src: ['**/*.css'],
dest: 'docs/examples/'
}
},
csslint: {
options: {
csslintrc: 'less/.csslintrc'
},
dist: [
'dist/css/bootstrap.css',
'dist/css/bootstrap-theme.css'
],
examples: [
'docs/examples/**/*.css'
],
docs: {
options: {
ids: false,
'overqualified-elements': false
},
src: 'docs/assets/css/src/docs.css'
}
},
cssmin: {
options: {
// TODO: disable `zeroUnits` optimization once clean-css 3.2 is released
// and then simplify the fix for https://github.com/twbs/bootstrap/issues/14837 accordingly
compatibility: 'ie8',
keepSpecialComments: '*',
sourceMap: true,
advanced: false
},
minifyCore: {
src: 'dist/css/<%= pkg.name %>.css',
dest: 'dist/css/<%= pkg.name %>.min.css'
},
minifyTheme: {
src: 'dist/css/<%= pkg.name %>-theme.css',
dest: 'dist/css/<%= pkg.name %>-theme.min.css'
},
docs: {
src: [
'docs/assets/css/ie10-viewport-bug-workaround.css',
'docs/assets/css/src/pygments-manni.css',
'docs/assets/css/src/docs.css'
],
dest: 'docs/assets/css/docs.min.css'
}
},
csscomb: {
options: {
config: 'less/.csscomb.json'
},
dist: {
expand: true,
cwd: 'dist/css/',
src: ['*.css', '!*.min.css'],
dest: 'dist/css/'
},
examples: {
expand: true,
cwd: 'docs/examples/',
src: '**/*.css',
dest: 'docs/examples/'
},
docs: {
src: 'docs/assets/css/src/docs.css',
dest: 'docs/assets/css/src/docs.css'
}
},
copy: {
fonts: {
expand: true,
src: 'fonts/*',
dest: 'dist/'
},
docs: {
expand: true,
cwd: 'dist/',
src: [
'**/*'
],
dest: 'docs/dist/'
}
},
connect: {
server: {
options: {
port: 3000,
base: '.'
}
}
},
jekyll: {
options: {
config: '_config.yml'
},
docs: {},
github: {
options: {
raw: 'github: true'
}
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
minifyCSS: true,
minifyJS: true,
removeAttributeQuotes: true,
removeComments: true
},
expand: true,
cwd: '_gh_pages',
dest: '_gh_pages',
src: [
'**/*.html',
'!examples/**/*.html'
]
}
},
jade: {
options: {
pretty: true,
data: getLessVarsData
},
customizerVars: {
src: 'docs/_jade/customizer-variables.jade',
dest: 'docs/_includes/customizer-variables.html'
},
customizerNav: {
src: 'docs/_jade/customizer-nav.jade',
dest: 'docs/_includes/nav/customize.html'
}
},
htmllint: {
options: {
ignore: [
'Attribute "autocomplete" not allowed on element "button" at this point.',
'Attribute "autocomplete" is only allowed when the input type is "color", "date", "datetime", "datetime-local", "email", "month", "number", "password", "range", "search", "tel", "text", "time", "url", or "week".',
'Element "img" is missing required attribute "src".'
]
},
src: '_gh_pages/**/*.html'
},
watch: {
src: {
files: '<%= jshint.core.src %>',
tasks: ['jshint:core', 'qunit', 'concat']
},
test: {
files: '<%= jshint.test.src %>',
tasks: ['jshint:test', 'qunit']
},
less: {
files: 'less/**/*.less',
tasks: 'less'
}
},
sed: {
versionNumber: {
pattern: (function () {
var old = grunt.option('oldver');
return old ? RegExp.quote(old) : old;
})(),
replacement: grunt.option('newver'),
exclude: [
'dist/fonts',
'docs/assets',
'fonts',
'js/tests/vendor',
'node_modules',
'test-infra'
],
recursive: true
}
},
'saucelabs-qunit': {
all: {
options: {
build: process.env.TRAVIS_JOB_ID,
throttled: 10,
maxRetries: 3,
maxPollRetries: 4,
urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'],
browsers: grunt.file.readYAML('grunt/sauce_browsers.yml')
}
}
},
exec: {
npmUpdate: {
command: 'npm update'
}
},
compress: {
main: {
options: {
archive: 'bootstrap-<%= pkg.version %>-dist.zip',
mode: 'zip',
level: 9,
pretty: true
},
files: [
{
expand: true,
cwd: 'dist/',
src: ['**'],
dest: 'bootstrap-<%= pkg.version %>-dist'
}
]
}
}
});
// These plugins provide necessary tasks.
require('load-grunt-tasks')(grunt, { scope: 'devDependencies' });
require('time-grunt')(grunt);
// Docs HTML validation task
grunt.registerTask('validate-html', ['jekyll:docs', 'htmllint']);
var runSubset = function (subset) {
return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset;
};
var isUndefOrNonZero = function (val) {
return val === undefined || val !== '0';
};
// Test task.
var testSubtasks = [];
// Skip core tests if running a different subset of the test suite
if (runSubset('core') &&
// Skip core tests if this is a Savage build
process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') {
testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'csslint:dist', 'test-js', 'docs']);
}
// Skip HTML validation if running a different subset of the test suite
if (runSubset('validate-html') &&
// Skip HTML5 validator on Travis when [skip validator] is in the commit message
isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) {
testSubtasks.push('validate-html');
}
// Only run Sauce Labs tests if there's a Sauce access key
if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' &&
// Skip Sauce if running a different subset of the test suite
runSubset('sauce-js-unit') &&
// Skip Sauce on Travis when [skip sauce] is in the commit message
isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) {
testSubtasks.push('connect');
testSubtasks.push('saucelabs-qunit');
}
grunt.registerTask('test', testSubtasks);
grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']);
// JS distribution task.
grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']);
// CSS distribution task.
grunt.registerTask('less-compile', ['less:compileCore', 'less:compileTheme']);
grunt.registerTask('dist-css', ['less-compile', 'autoprefixer:core', 'autoprefixer:theme', 'csscomb:dist', 'cssmin:minifyCore', 'cssmin:minifyTheme']);
// Full distribution task.
grunt.registerTask('dist', ['clean:dist', 'dist-css', 'copy:fonts', 'dist-js']);
// Default task.
grunt.registerTask('default', ['clean:dist', 'copy:fonts', 'test']);
// Version numbering task.
// grunt change-version-number --oldver=A.B.C --newver=X.Y.Z
// This can be overzealous, so its changes should always be manually reviewed!
grunt.registerTask('change-version-number', 'sed');
grunt.registerTask('build-glyphicons-data', function () { generateGlyphiconsData.call(this, grunt); });
// task for building customizer
grunt.registerTask('build-customizer', ['build-customizer-html', 'build-raw-files']);
grunt.registerTask('build-customizer-html', 'jade');
grunt.registerTask('build-raw-files', 'Add scripts/less files to customizer.', function () {
var banner = grunt.template.process('<%= banner %>');
generateRawFiles(grunt, banner);
});
grunt.registerTask('commonjs', 'Generate CommonJS entrypoint module in dist dir.', function () {
var srcFiles = grunt.config.get('concat.bootstrap.src');
var destFilepath = 'dist/js/npm.js';
generateCommonJSModule(grunt, srcFiles, destFilepath);
});
// Docs task.
grunt.registerTask('docs-css', ['autoprefixer:docs', 'autoprefixer:examples', 'csscomb:docs', 'csscomb:examples', 'cssmin:docs']);
grunt.registerTask('lint-docs-css', ['csslint:docs', 'csslint:examples']);
grunt.registerTask('docs-js', ['uglify:docsJs', 'uglify:customize']);
grunt.registerTask('lint-docs-js', ['jshint:assets', 'jscs:assets']);
grunt.registerTask('docs', ['docs-css', 'lint-docs-css', 'docs-js', 'lint-docs-js', 'clean:docs', 'copy:docs', 'build-glyphicons-data', 'build-customizer']);
grunt.registerTask('prep-release', ['dist', 'docs', 'jekyll:github', 'htmlmin', 'compress']);
// Task for updating the cached npm packages used by the Travis build (which are controlled by test-infra/npm-shrinkwrap.json).
// This task should be run and the updated file should be committed whenever Bootstrap's dependencies change.
grunt.registerTask('update-shrinkwrap', ['exec:npmUpdate', '_update-shrinkwrap']);
grunt.registerTask('_update-shrinkwrap', function () {
var done = this.async();
npmShrinkwrap({ dev: true, dirname: __dirname }, function (err) {
if (err) {
grunt.fail.warn(err);
}
var dest = 'test-infra/npm-shrinkwrap.json';
fs.renameSync('npm-shrinkwrap.json', dest);
grunt.log.writeln('File ' + dest.cyan + ' updated.');
done();
});
});
};

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2011-2015 Twitter, Inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,139 @@
# [Bootstrap](http://getbootstrap.com)
[![Slack](https://bootstrap-slack.herokuapp.com/badge.svg)](https://bootstrap-slack.herokuapp.com)
![Bower version](https://img.shields.io/bower/v/bootstrap.svg)
[![npm version](https://img.shields.io/npm/v/bootstrap.svg)](https://www.npmjs.com/package/bootstrap)
[![Build Status](https://img.shields.io/travis/twbs/bootstrap/master.svg)](https://travis-ci.org/twbs/bootstrap)
[![devDependency Status](https://img.shields.io/david/dev/twbs/bootstrap.svg)](https://david-dm.org/twbs/bootstrap#info=devDependencies)
[![NuGet](https://img.shields.io/nuget/v/bootstrap.svg)](https://www.nuget.org/packages/Bootstrap)
[![Selenium Test Status](https://saucelabs.com/browser-matrix/bootstrap.svg)](https://saucelabs.com/u/bootstrap)