...
 
Commits (2)
{
"env": {
"browser": true,
"builtin": true,
"es6": true,
"jasmine": true,
"jquery": true,
"mocha": true,
"node": true
},
"globals": {
"Foundation": true
},
"parserOptions": {
"ecmaFeatures": {
"impliedStrict": true,
"jsx": false
},
"ecmaVersion": 6,
"sourceType": "module"
},
"rules": {
"block-scoped-var": 2,
"camelcase": 2,
"comma-style": [2, "last"],
"curly": [0, "all"],
"dot-notation": [
2,
{
"allowKeywords": true
}
],
"eqeqeq": [2, "allow-null"],
"guard-for-in": 2,
"new-cap": 2,
"no-bitwise": 2,
"no-caller": 2,
"no-cond-assign": [2, "except-parens"],
"no-debugger": 2,
"no-empty": 2,
"no-eval": 2,
"no-extend-native": 2,
"no-extra-parens": 1,
"no-irregular-whitespace": 2,
"no-iterator": 2,
"no-loop-func": 2,
"no-multi-str": 2,
"no-new": 2,
"no-plusplus": 0,
"no-proto": 2,
"no-script-url": 2,
"no-sequences": 2,
"no-shadow": 1,
"no-undef": 2,
"no-unused-vars": 1,
"no-with": 2,
"quotes": 0,
"radix" : 2,
"semi": [0, "never"],
"strict": [1, "global"],
"valid-typeof": 2,
"wrap-iife": [2, "inside"]
}
}
......@@ -4,6 +4,7 @@
.setting*
.nyc*
package-lock.json
node_modules
vendor
dist
......@@ -4,6 +4,17 @@ stages:
- test
- deploy
# Cache modules in between jobs
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
# cache JS dependencies
- node_modules/
# cache PHP dependencies
- vendor/
# cache package/project stuff, non-artifacts
- dist/
variables:
BUILD_TARGET: httpdocs
BUILD_LABEL_TMPFILE: build.txt
......@@ -11,22 +22,31 @@ variables:
before_script:
- if [ -f ${BUILD_LABEL_TMPFILE} ]; then export BUILD_LABEL=`cat ${BUILD_LABEL_TMPFILE}`; fi
init:
stage: setup
tags:
#- kunden-web
- kunden-web
#- node
- php
#- php
before_script:
- export BUILD_LABEL=$(TZ=Europe/Berlin date +%Y%m%d-%H%M)
script:
# save timestamp to file
- echo $BUILD_LABEL > ${BUILD_LABEL_TMPFILE}
- echo -e "\n\n\n\e[96mCreated new build label \e[107;30;1m $BUILD_LABEL \e[0m\n\n\n"
- echo -e "\n\n\e[96mCreated new build label \e[107;30;1m $BUILD_LABEL \e[0m\n\n"
# other init commands
- whoami
- pwd
- node -v
- npm -v
- php -v
# check if a build environment exists and copy it or install a new one if it doesn't
- if [ -d /build-env_DOES_NOT_EXIT_USE_INSTALL_FOR_NOW/node_modules ] && [ -f /build-env/package-lock.json ];
then echo -e "\e[96mFOUND EXISTING BUILD ENVIRONMENT" && mv /build-env/* ./;
else echo -e "\e[93mNO EXISTING BUILD ENVIRONMENT - RUNNING INSTALL" && npm install;
fi
# list used packages and info
- npm ls || true
artifacts:
paths:
- ${BUILD_LABEL_TMPFILE}
......@@ -34,29 +54,26 @@ init:
app-build:
stage: build
tags:
#- kunden-web
- kunden-web
#- node
- php
#- php
dependencies:
- init
variables:
BUILD_INFO_FILE: httpdocs/build.txt
script:
# check if a build environment exists and copy it or install a new one if it doesn't
- if [ -d /build-env_DOES_NOT_EXIT_USE_INSTALL_FOR_NOW/node_modules ] && [ -f /build-env/package-lock.json ];
then echo -e "\e[96mFOUND EXISTING BUILD ENVIRONMENT" && mv /build-env/* ./;
else echo -e "\e[93mNO EXISTING BUILD ENVIRONMENT - RUNNING INSTALL" && npm install;
fi
# list used packages
- npm ls || true
#
# run no build
#- echo "Warning - no build specified" && exit 0
#
# run node build
- npm -v
- php -v
- npm run build
# create build info file
- echo -e "LABEL=`cat ${BUILD_LABEL_TMPFILE}`" > ${BUILD_INFO_FILE}
- echo -e "TAG=${CI_COMMIT_TAG}" >> ${BUILD_INFO_FILE}
- echo -e "COMMIT=${CI_COMMIT_SHA}" >> ${BUILD_INFO_FILE}
- echo -e "PIPELINE=${CI_PIPELINE_ID}" >> ${BUILD_INFO_FILE}
- echo -e "USER=${GITLAB_USER_NAME} (${GITLAB_USER_LOGIN}) <${GITLAB_USER_EMAIL}>" >> ${BUILD_INFO_FILE}
# print debug-info
- cat ${BUILD_INFO_FILE}
- ls -la ${BUILD_TARGET}
......@@ -65,54 +82,104 @@ app-build:
- ${BUILD_TARGET}
app-tests:
app-test-sass:
stage: test
tags:
#- kunden-web
#- node
- php
- kunden-web
dependencies:
- app-build
variables:
BUILD_TEST_COVERAGE_FILE: httpdocs/coverage.xml
script:
# check if a build environment exists and copy it or install a new one if it doesn't
- php -v
- node -v
#
# run no tests
#- echo "Warning - no SASS tests specified" && exit 0
#
# run SASS tests
- npm run test:sass
artifacts:
paths:
- ${BUILD_TARGET}
app-test-javascript:
stage: test
tags:
- kunden-web
dependencies:
- app-build
script:
#
# run no tests
#- echo "Warning - no JavaScript tests specified" && exit 0
#
# run SASS tests
- npm run test:javascript
artifacts:
paths:
- ${BUILD_TARGET}
rsync:
stage: deploy
app-test-browser:
stage: test
tags:
- web-rsync-runner
- kunden-web
dependencies:
- app-build
- app-tests
before_script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- ssh-add <(echo "$SSH_STAGING_PRIVATE_KEY")
- apt-get install rsync
script:
- ssh -p22 user@staging.example.com "mkdir -p /_tmp"
- rsync -rav -e ssh --exclude='.git/' --exclude='.gitlab-ci.yml' --delete-excluded /${BUILD_TARGET}/ user@staging.example.com:/_tmp
- ssh -p22 user@staging.example.com "mv /${BUILD_TARGET} /${BUILD_TARGET}_save && mv /_tmp /${BUILD_TARGET}"
- ssh -p22 user@staging.example.com "rm -rf /${BUILD_TARGET}_save"
only:
refs:
- master
when: manual
#
# run no tests
#- echo "Warning - no browser tests specified" && exit 0
#
# run browser/headless tests
- npm run test:browser
artifacts:
paths:
- ${BUILD_TARGET}
src-lint-sass:
stage: test
tags:
- kunden-web
dependencies:
- app-build
script:
#
# run no linting
#- echo "Warning - no SASS linting specified" && exit 0
#
# run SASS linting
- npm run lint:sass
artifacts:
paths:
- ${BUILD_TARGET}
src-lint-javascript:
stage: test
tags:
- kunden-web
dependencies:
- app-build
script:
#
# run no linting
#- echo "Warning - no JavaScript linting specified" && exit 0
#
# run SASS linting
- npm run lint:javascript
artifacts:
paths:
- ${BUILD_TARGET}
# ftp to dev host
ftp-dev:
stage: deploy
tags:
- kunden-web
dependencies:
- app-build
- app-tests
before_script:
#- no action for now...
script:
# deploy files
- npm run deploy
# ftp to host
- 'which lftp || ( apt-get update -qq && apt-get install -y -qq lftp )'
- lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST; mirror -Rev ${BUILD_TARGET}/ ./$FTP_PATH/${BUILD_TARGET} --parallel=10 --exclude-glob .git* --exclude .git/"
except:
......@@ -121,20 +188,30 @@ ftp-dev:
- tags
- release
when: manual
artifacts:
paths:
- ${BUILD_TARGET}
# ftp to production/live host
ftp-prod:
stage: deploy
tags:
- kunden-web
dependencies:
- app-build
- app-tests
before_script:
#- no action for now...
script:
# deploy files
- npm run deploy
# ftp to host
- 'which lftp || ( apt-get update -qq && apt-get install -y -qq lftp )'
- lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME_PROD,$FTP_PASSWORD_PROD $FTP_HOST_PROD; mirror -Rev ${BUILD_TARGET}/ ./$FTP_PATH_PROD/${BUILD_TARGET} --parallel=10 --exclude-glob .git* --exclude .git/"
only:
refs:
- master
- tags
- release
when: manual
artifacts:
paths:
- ${BUILD_TARGET}
options:
formatter: stylish
files:
include: '**/*.s+(a|c)ss'
ignore: ''
rules:
# Extends
extends-before-mixins: 1
extends-before-declarations: 1
placeholder-in-extend: 1
# Mixins
mixins-before-declarations: 1
# Line Spacing
one-declaration-per-line: 1
empty-line-between-blocks: 1
single-line-per-selector: 1
# Disallows
no-attribute-selectors: 0
no-color-hex: 0
no-color-keywords: 1
no-color-literals: 1
no-combinators: 0
no-css-comments: 1
no-debug: 1
no-disallowed-properties: 0
no-duplicate-properties: 1
no-empty-rulesets: 1
no-extends: 0
no-ids: 1
no-important: 1
no-invalid-hex: 1
no-mergeable-selectors: 1
no-misspelled-properties: 1
no-qualifying-elements: 1
no-trailing-whitespace: 1
no-trailing-zero: 1
no-transition-all: 1
no-universal-selectors: 0
no-url-domains: 1
no-url-protocols: 1
no-vendor-prefixes: 1
no-warn: 1
property-units: 0
# Nesting
declarations-before-nesting: 1
force-attribute-nesting: 1
force-element-nesting: 1
force-pseudo-nesting: 1
# Name Formats
class-name-format: 1
function-name-format: 1
id-name-format: 0
mixin-name-format: 1
placeholder-name-format: 1
variable-name-format: 1
# Style Guide
attribute-quotes: 1
bem-depth: 0
border-zero: 1
brace-style: 1
clean-import-paths: 1
empty-args: 1
hex-length: 1
hex-notation: 1
indentation: 1
leading-zero: 1
max-line-length: 0
max-file-line-count: 0
nesting-depth: 1
property-sort-order: 1
pseudo-element: 1
quotes: 1
shorthand-values: 1
url-quotes: 1
variable-for-property: 1
zero-unit: 1
# Inner Spacing
space-after-comma: 1
space-before-colon: 1
space-after-colon: 1
space-before-brace: 1
space-before-bang: 1
space-after-bang: 1
space-between-parens: 1
space-around-operator: 1
# Final Items
trailing-semicolon: 1
final-newline: 1
{
"name": "p-ad/web-base",
"name": "web-base",
"version": "0.0.1",
"license": "MIT",
"require": {}
}
# Your project's server will run on localhost:xxxx at this port
PORT: 8000
# Autoprefixer will make sure your CSS works with these browsers
COMPATIBILITY:
- "last 2 versions"
- "ie >= 9"
- "ios >= 7"
# UnCSS will use these settings
UNCSS_OPTIONS:
html:
# Search for used CSS classes in generated HTML files
- "dist/**/*.html"
ignore:
- !!js/regexp .foundation-mq
- !!js/regexp ^\.is-.*
# Gulp will reference these paths when it copies files
PATHS:
# Path to dist folder
dist: "dist"
# Paths to static assets that aren't images, CSS, or JavaScript
assets:
- "src/assets/**/*"
- "!src/assets/{img,js,scss}/**/*"
# Paths to Sass libraries, which can then be loaded with @import
sass:
- "node_modules/foundation-sites/scss"
- "node_modules/motion-ui/src"
# Paths to JavaScript entry points for webpack to bundle modules
entries:
- "src/assets/js/*.js"
deploy:
pages:
source: "dist/**/*.html"
target: "httpdocs/"
css:
source: "dist/assets/css/**/*"
target: "httpdocs/assets/css/"
js:
source: "dist/assets/js/**/*"
target: "httpdocs/assets/js/"
img:
source: "dist/assets/img/**/*"
target: "httpdocs/assets/img/"
'use strict';
import plugins from 'gulp-load-plugins';
import yargs from 'yargs';
import browser from 'browser-sync';
import gulp from 'gulp';
import panini from 'panini';
import rimraf from 'rimraf';
import sherpa from 'style-sherpa';
import yaml from 'js-yaml';
import fs from 'fs';
import webpackStream from 'webpack-stream';
import webpack2 from 'webpack';
import named from 'vinyl-named';
import uncss from 'uncss';
import autoprefixer from 'autoprefixer';
// Load all Gulp plugins into one variable
const $ = plugins();
// Check for --production flag
const PRODUCTION = !!(yargs.argv.production);
// Load settings from settings.yml
const { COMPATIBILITY, PORT, UNCSS_OPTIONS, PATHS } = loadConfig();
function loadConfig() {
let ymlFile = fs.readFileSync('config.yml', 'utf8');
return yaml.load(ymlFile);
}
// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
rimraf(PATHS.dist, done);
}
// Copy files out of the assets folder
// This task skips over the "img", "js", and "scss" folders, which are parsed separately
function copy() {
return gulp.src(PATHS.assets)
.pipe(gulp.dest(PATHS.dist + '/assets'));
}
// Copy page templates into finished HTML files
function pages() {
return gulp.src('src/pages/**/*.{html,hbs,handlebars}')
.pipe(panini({
root: 'src/pages/',
layouts: 'src/layouts/',
partials: 'src/partials/',
data: 'src/data/',
helpers: 'src/helpers/'
}))
.pipe(gulp.dest(PATHS.dist));
}
// Load updated HTML templates and partials into Panini
function resetPages(done) {
panini.refresh();
done();
}
// Generate a style guide from the Markdown content and HTML template in styleguide/
function styleGuide(done) {
sherpa('src/styleguide/index.md', {
output: PATHS.dist + '/styleguide.html',
template: 'src/styleguide/template.html'
}, done);
}
// Compile Sass into CSS
// In production, the CSS is compressed
function sass() {
const postCssPlugins = [
// Autoprefixer
autoprefixer({ browsers: COMPATIBILITY }),
// UnCSS - Uncomment to remove unused styles in production
// PRODUCTION && uncss.postcssPlugin(UNCSS_OPTIONS),
].filter(Boolean);
return gulp.src('src/assets/scss/*.scss')
.pipe($.sourcemaps.init())
.pipe($.sass({
includePaths: PATHS.sass
})
.on('error', $.sass.logError))
.pipe($.postcss(postCssPlugins))
.pipe($.if(PRODUCTION, $.cleanCss({ compatibility: 'ie9' })))
.pipe($.if(!PRODUCTION, $.sourcemaps.write()))
.pipe(gulp.dest(PATHS.dist + '/assets/css'))
.pipe(browser.reload({ stream: true }));
}
let webpackConfig = {
mode: (PRODUCTION ? 'production' : 'development'),
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [ "@babel/preset-env" ],
compact: false
}
}
}
]
},
devtool: !PRODUCTION && 'source-map'
}
// Combine JavaScript into one file
// In production, the file is minified
function javascript() {
return gulp.src(PATHS.entries)
.pipe(named())
.pipe($.sourcemaps.init())
.pipe(webpackStream(webpackConfig, webpack2))
.pipe($.if(PRODUCTION, $.uglify()
.on('error', e => { console.log(e); })
))
.pipe($.if(!PRODUCTION, $.sourcemaps.write()))
.pipe(gulp.dest(PATHS.dist + '/assets/js'));
}
// Copy images to the "dist" folder
// In production, the images are compressed
function images() {
return gulp.src('src/assets/img/**/*')
.pipe($.if(PRODUCTION, $.imagemin([
$.imagemin.jpegtran({ progressive: true }),
])))
.pipe(gulp.dest(PATHS.dist + '/assets/img'));
}
// Start a server with BrowserSync to preview the site in
function server(done) {
browser.init({
server: PATHS.dist, port: PORT
}, done);
}
// Reload the browser with BrowserSync
function reload(done) {
browser.reload();
done();
}
// Watch for changes to static assets, pages, Sass, and JavaScript
function watch() {
gulp.watch(PATHS.assets, copy);
gulp.watch('src/pages/**/*.html').on('all', gulp.series(pages, browser.reload));
gulp.watch('src/{layouts,partials}/**/*.html').on('all', gulp.series(resetPages, pages, browser.reload));
gulp.watch('src/data/**/*.{js,json,yml}').on('all', gulp.series(resetPages, pages, browser.reload));
gulp.watch('src/helpers/**/*.js').on('all', gulp.series(resetPages, pages, browser.reload));
gulp.watch('src/assets/scss/**/*.scss').on('all', sass);
gulp.watch('src/assets/js/**/*.js').on('all', gulp.series(javascript, browser.reload));
gulp.watch('src/assets/img/**/*').on('all', gulp.series(images, browser.reload));
gulp.watch('src/styleguide/**').on('all', gulp.series(styleGuide, browser.reload));
}
// Deploy/copy HTML files
gulp.task('deploy:pages', () => {
return ( gulp.src( PATHS.deploy.pages.source ).pipe( gulp.dest(PATHS.deploy.pages.target) ) )
});
// Deploy/copy CSS files
gulp.task('deploy:stylesheets', () => {
return ( gulp.src( PATHS.deploy.css.source ).pipe( gulp.dest(PATHS.deploy.css.target) ) )
});
// Deploy/copy JS files
gulp.task('deploy:javascript', () => {
return ( gulp.src( PATHS.deploy.js.source ).pipe( gulp.dest(PATHS.deploy.js.target) ) )
});
// Deploy/copy images
gulp.task('deploy:images', () => {
return ( gulp.src( PATHS.deploy.img.source ).pipe( gulp.dest(PATHS.deploy.img.target) ) )
});
// Deploy/copy files
gulp.task('deploy', gulp.parallel('deploy:pages', 'deploy:stylesheets', 'deploy:javascript', 'deploy:images'));
// Build the "dist" folder by running all of the below tasks
// Sass must be run later so UnCSS can search for used classes in the others assets.
gulp.task('build', gulp.series(clean, gulp.parallel(pages, javascript, images, copy), sass, styleGuide /*, 'deploy'*/ ));
// Build the site, run the server, and watch for file changes
gulp.task('default', gulp.series('build', server, watch));
{
"name": "web-base",
"version": "1.0.0",
"version": "0.0.1",
"description": "",
"main": "index.js",
"author": "coding@bjoernbartels.earth",
"license": "MIT",
"repository": {
"type": "git",
"url": "git@gitlab.bjoernbartels.earth/devops/web-base.git"
},
"bugs": {
"url": "https://gitlab.bjoernbartels.earth/devops/web-base/issues",
"email": "coding@bjoernbartels.earth"
},
"private": false,
"main": "gulpfile.babel.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"start": "gulp",
"build": "gulp build --production",
"build:dev": "gulp build",
"lint": "npm run lint:sass && npm run lint:javascript",
"lint:sass": "sass-lint './src/assets/scss/**/*.scss'",
"lint:javascript": "./node_modules/.bin/eslint ./src/assets/js/**/*.js",
"test": "npm run test:sass && npm run test:javascript && npm run test:browser",
"test:sass": "mocha ./test/sass/*.js",
"test:javascript": "nyc mocha --require '@babel/register' ./test/js/*.js;",
"test:browser": "mocha-headless-chrome -a no-sandbox -f ./test/headless/*.html -c ./dist/coverage.json",
"deploy": "gulp deploy",
"reinstall": "rm -rf node_modules package-lock.json; npm install;"
},
"dependencies": {
"aos": "^2.2.0",
"foundation-sites": "^6.5",
"jquery": "^3",
"jquery-ui": "^1",
"motion-ui": "^2.0.3",
"what-input": "^5.1.2"
},
"devDependencies": {
"@babel/core": "^7.1.2",
"@babel/preset-env": "^7.1.0",
"@babel/register": "^7.0.0",
"autoprefixer": "^9.1.5",
"babel-loader": "^8.0.4",
"browser-sync": "^2.10.0",
"gulp": "^4.0.0",
"gulp-babel": "^8.0.0",
"gulp-clean-css": "^3.3.1",
"gulp-eslint": "^3.0.1",
"gulp-sass-lint": "^1.3.2",
"gulp-cli": "^2.0.1",
"gulp-concat": "^2.5.2",
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.4",
"gulp-extname": "^0.2.0",
"gulp-if": "^2.0.0",
"gulp-imagemin": "^4.1.0",
"gulp-load-plugins": "^1.1.0",
"gulp-postcss": "^8.0.0",
"gulp-sass": "^4.0.1",
"gulp-sourcemaps": "^2.6.4",
"gulp-uglify": "^3.0.1",
"js-yaml": "^3.4.6",
"panini": "^1.3.0",
"rimraf": "^2.4.3",
"style-sherpa": "^1.0.0",
"uncss": "^0.16.2",
"vinyl-named": "^1.1.0",
"webpack": "^4.20.2",
"webpack-stream": "^5.1.1",
"yargs": "^12.0.2",
"chai": "^4",
"chai-jquery": "^2",
"mocha": "^5",
"mocha-headless-chrome": "^2",
"mocha-lcov-reporter": "^1",
"nyc": "^13",
"sinon": "^7",
"sass-true": "^2.2.2",
"sass-lint": "^1.12.1",
"eslint": "^5.8.0"
},
"browserify": {
"transform": [
[
"babelify",
{
"presets": [
"@babel/preset-env"
]
}
]
]
},
"babel": {
"presets": [
"@babel/preset-env"
]
},
"author": "",
"license": "MIT"
"nyc": {
"include": [
"./src/assets/js/**/*.js"
],
"exclude": [],
"reporter": [
"lcov",
"clover",
"html",
"text-summary"
],
"report-dir": "./dist/coverage",
"instrument": true,
"sourceMap": true
}
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>web-base</title>
<link rel="stylesheet" href="/assets/css/app.css" />
<script src="/assets/js/app.js"></script>
</head>
<body>
{{> body}}
</body>
</html>
This diff is collapsed.
<header class="row">
<div class="large-12 columns">
<h1>[Theme]</h1>
</div>
</header>
<div class="row">
<div class="large-12 columns">
<h2>Pages</h2>
<ul>
<li><a href="/htmlelements.html">HTML elements</a></li>
<li><a href="/styleguide.html">Styleguide</a></li>
</ul>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<h2>Info</h2>
<ul>
<li><a href="/build.txt">build info</a></li>
</ul>
</div>
</div>
This diff is collapsed.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>[Theme - Style Guide]</title>
<link rel="stylesheet" href="assets/css/app.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/styles/github.min.css">
<!-- Style guide-specific CSS goes here. -->
<style>
/* This styles individual sections of the style guide */
.ss-section:not(:last-child) {
padding-bottom: 4rem;
border-bottom: 2px solid #ccc;
margin-bottom: 4rem;
}
/* This styles code blocks used for examples. */
.ss-code code {
display: block;
padding: 1rem;
overflow-x: scroll;
margin-bottom: 1.5rem;
}
/* This styles the example rows used in the grid documentation. */
.grid-x.display {
background: #eee;
font-size: 11px;
margin-bottom: 10px;
line-height: 2rem;
border: solid 1px #c6c6c6;
margin-left: 0 !important;
margin-right: 0 !important; }
.grid-x.display .cell:nth-child(2), .grid-x.display .cell.small-centered, .grid-x.display .cell.large-centered {
background: #e1e1e1; }
.grid-x.display .cell.color-end {
background: #d4d4d4; }
/* This styles the color blocks used in the color documentation. */
.color-block {
border-radius: 2px;
display: block;
padding: 8px 8px 6px;
color: #333;
text-transform: uppercase;
border: 1px solid #ddd;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
}
.color-block span {
display: block;
width: 100%;
height: 100px;
margin-bottom: 0.42857rem;
}
.sg-header {
background: #eee;
padding: 2rem;
}
.grid-container {
max-width: 1400px;
}
.sg-side-menu {
margin-left: 1rem;
}
.grid-container.padded {
padding-top: 2rem;
}
.sg-side-menu a {
transition: all 0.15s ease-in;
}
.sg-side-menu a:hover {
background: #eee;
}
.sg-side-menu a:focus {
background: #1468a0;
color: #fff;
}
.sg-side-menu.menu {
overflow: auto;
height: 100vh;
padding-bottom: 5rem;
}
</style>
</head>
<body>
<header class="sg-header" id="sg-header">
<div class="grid-container">
<h1>[Theme - Style Guide]</h1>
<p class="lead">This style guide was built with Foundation for Sites. For more information on how to use this responsive front-end framework, check out the documentation, get help from the Foundation community, or request immediate technical support.</p>
<a href="http://foundation.zurb.com/docs/" class="button">Visit the Docs</a>
<a href="http://foundation.zurb.com/forum/" class="secondary button">Foundation Forum</a>
<a href="http://foundation.zurb.com/business/business-support.html" class="secondary button">Technical Support</a>
</div>
</header>
<div class="grid-container padded">
<div class="grid-x grid-margin-x" data-sticky-container>
<div class="large-3 medium-4 cell">
<div class="sticky" data-sticky data-top-anchor="sg-header:bottom">
<ul class="vertical menu sg-side-menu" data-smooth-scroll data-animation-easing="swing">
{{#each pages}}
<li><a href="#{{ anchor }}">{{ title }}</a></li>
{{/each}}
</ul>
</div>
</div>
<div class="large-9 medium-8 cell">
{{#each pages}}
<section class="ss-section" id="{{ anchor }}">
{{ body }}
</section>
{{/each}}
</div>
</div>
</div>
<script src="assets/js/app.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="lib/mocha.css">
<link rel="stylesheet" href="../../dist/assets/css/app.css">
<!-- -a ignore-resource-errors -->
</head>
<body>
<div id="mocha"></div>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="../lib/mocha.js"></script>
<script src="../lib/chai.js"></script>
<script src="../lib/chai-jquery.js"></script>
<script src="../lib/sinon.js"></script>
<script>
mocha.setup('bdd');
chai.should();
</script>
<script src="../../dist/assets/js/app.js"></script>
<script src="../lib/keyboard-event-mock.js"></script>
<script src="../headless/tests.js"></script>
<script>
if (window.mochaPhantomJS) { mochaPhantomJS.run(); }
else { mocha.run(); }
</script>
</body>
</html>
(function (chaiJquery) {
// Module systems magic dance.
if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
// NodeJS
module.exports = chaiJquery;
} else if (typeof define === "function" && define.amd) {
// AMD
define(['jquery'], function ($) {
return function (chai, utils) {
return chaiJquery(chai, utils, $);
};
});
} else {
// Other environment (usually <script> tag): plug in to global chai instance directly.
chai.use(function (chai, utils) {
return chaiJquery(chai, utils, jQuery);
});
}
}(function (chai, utils, $) {
var inspect = utils.inspect,
flag = utils.flag;
$ = $ || jQuery;
var setPrototypeOf = '__proto__' in Object ?
function (object, prototype) {
object.__proto__ = prototype;
} :
function (object, prototype) {
var excludeNames = /^(?:length|name|arguments|caller)$/;
function copyProperties(dst, src) {
Object.getOwnPropertyNames(src).forEach(function (name) {
if (!excludeNames.test(name)) {
Object.defineProperty(dst, name,
Object.getOwnPropertyDescriptor(src, name));
}
});
}
copyProperties(object, prototype);
copyProperties(object, Object.getPrototypeOf(prototype));
};
$.fn.inspect = function (depth) {
var el = $('<div />').append(this.clone());
if (depth !== undefined) {
var children = el.children();
while (depth-- > 0)
children = children.children();
children.html('...');
}
return el.html();
};
var props = {attr: 'attribute', css: 'CSS property', prop: 'property'};
for (var prop in props) {
(function (prop, description) {
chai.Assertion.addMethod(prop, function (name, val) {
var actual = flag(this, 'object')[prop](name);
if (!flag(this, 'negate') || undefined === val) {
this.assert(
undefined !== actual
, 'expected #{this} to have a #{exp} ' + description
, 'expected #{this} not to have a #{exp} ' + description
, name
);
}
if (undefined !== val) {
this.assert(
val === actual
, 'expected #{this} to have a ' + inspect(name) + ' ' + description + ' with the value #{exp}, but the value was #{act}'
, 'expected #{this} not to have a ' + inspect(name) + ' ' + description + ' with the value #{act}'
, val
, actual
);
}
flag(this, 'object', actual);
});
})(prop, props[prop]);
}
chai.Assertion.addMethod('data', function (name, val) {
// Work around a chai bug (https://github.com/logicalparadox/chai/issues/16)
if (flag(this, 'negate') && undefined !== val && undefined === flag(this, 'object').data(name)) {
return;
}
var assertion = new chai.Assertion(flag(this, 'object').data());
if (flag(this, 'negate'))
assertion = assertion.not;
return assertion.property(name, val);
});
chai.Assertion.addMethod('class', function (className) {
this.assert(
flag(this, 'object').hasClass(className)
, 'expected #{this} to have class #{exp}'
, 'expected #{this} not to have class #{exp}'
, className
);
});
chai.Assertion.addMethod('id', function (id) {
this.assert(
flag(this, 'object').attr('id') === id
, 'expected #{this} to have id #{exp}'
, 'expected #{this} not to have id #{exp}'
, id
);
});
chai.Assertion.addMethod('html', function (html) {
var actual = flag(this, 'object').html();
this.assert(
actual === html
, 'expected #{this} to have HTML #{exp}, but the HTML was #{act}'
, 'expected #{this} not to have HTML #{exp}'
, html
, actual
);
});
chai.Assertion.addMethod('text', function (text) {
var actual = flag(this, 'object').text();
this.assert(
actual === text
, 'expected #{this} to have text #{exp}, but the text was #{act}'
, 'expected #{this} not to have text #{exp}'
, text
, actual
);
});
chai.Assertion.addMethod('value', function (value) {
var actual = flag(this, 'object').val();
this.assert(
flag(this, 'object').val() === value
, 'expected #{this} to have value #{exp}, but the value was #{act}'
, 'expected #{this} not to have value #{exp}'
, value
, actual
);
});
chai.Assertion.addMethod('descendants', function (selector) {
this.assert(
flag(this, 'object').has(selector).length > 0
, 'expected #{this} to have #{exp}'
, 'expected #{this} not to have #{exp}'
, selector
);
});
$.each(['visible', 'hidden', 'selected', 'checked', 'enabled', 'disabled'], function (i, attr) {
chai.Assertion.addProperty(attr, function () {
this.assert(
flag(this, 'object').is(':' + attr)
, 'expected #{this} to be ' + attr
, 'expected #{this} not to be ' + attr);
});
});
chai.Assertion.overwriteProperty('exist', function (_super) {
return function () {
var obj = flag(this, 'object');
if (obj instanceof $) {
this.assert(
obj.length > 0
, 'expected ' + inspect(obj.selector) + ' to exist'
, 'expected ' + inspect(obj.selector) + ' not to exist');
} else {
_super.apply(this, arguments);
}
};
});
chai.Assertion.overwriteProperty('empty', function (_super) {
return function () {
var obj = flag(this, 'object');
if (obj instanceof $) {
this.assert(
obj.is(':empty')
, 'expected #{this} to be empty'
, 'expected #{this} not to be empty');
} else {
_super.apply(this, arguments);
}
};
});
chai.Assertion.overwriteMethod('match', function (_super) {
return function (selector) {
var obj = flag(this, 'object');
if (obj instanceof $) {
this.assert(
obj.is(selector)
, 'expected #{this} to match #{exp}'
, 'expected #{this} not to match #{exp}'
, selector
);
} else {
_super.apply(this, arguments);
}
}
});
chai.Assertion.overwriteChainableMethod('contain',
function (_super) {
return function (text) {
var obj = flag(this, 'object');
if (obj instanceof $) {
this.assert(
obj.is(':contains(\'' + text + '\')')
, 'expected #{this} to contain #{exp}'
, 'expected #{this} not to contain #{exp}'
, text);
} else {
_super.apply(this, arguments);
}
}
},
function(_super) {
return function() {
_super.call(this);
};
}
);
}));
This diff is collapsed.
(function(global) {
var keyCodes = {
'A': 65,
'TAB': 9,
'ENTER': 13,
'ESCAPE': 27,
'SPACE': 32,
'END': 35,
'HOME': 36,
'ARROW_LEFT': 37,
'ARROW_UP': 38,
'ARROW_RIGHT': 39,
'ARROW_DOWN': 40
};
/**
* Creates a dummy event to parse.
* Uses jQuery Event class constructor.
* @param {number} keyCode Key code of the key that is simulated.
* @param {object} opts Options that say if modifiers are pressed.
* @return {Event} Event to use.
*/
global.mockKeyboardEvent = mockKeyboardEvent = function(keyCode, opts) {
var options = opts || {},
isCtrl = !!options.ctrl,
isAlt = !!options.alt,
isShift = !!options.shift,
isMeta = !!options.meta,
keyCode = typeof keyCode === 'number' ? keyCode : keyCodes[keyCode],
event = {
shiftKey: isShift,
altKey: isAlt,
ctrlKey: isCtrl,
metaKey: isMeta,
keyCode: keyCode,
which: keyCode
};
return new $.Event('keydown', event);
};
})(window);
\ No newline at end of file
@charset "utf-8";
body {
margin:0;
}
#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 60px 50px;
}
#mocha ul,
#mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1,
#mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
#mocha .hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial, sans-serif;
}
#mocha .test.pass.medium .duration {
background: #c09853;
}
#mocha .test.pass.slow .duration {
background: #b94a48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: #fff;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
#mocha .test .html-error {
overflow: auto;
color: black;
line-height: 1.5;
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
max-width: 85%; /*(1)*/
max-width: calc(100% - 42px); /*(2)*/
max-height: 300px;
word-wrap: break-word;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
border-radius: 3px;
}
#mocha .test .html-error pre.error {
border: none;
-webkit-border-radius: none;
-webkit-box-shadow: none;
-moz-border-radius: none;
-moz-box-shadow: none;
padding: 0;
margin: 0;
margin-top: 18px;
max-height: none;
}
/**
* (1): approximate for browsers not supporting calc
* (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
* ^^ seriously
*/
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
max-width: 85%; /*(1)*/
max-width: calc(100% - 42px); /*(2)*/
word-wrap: break-word;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
border-radius: 3px;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
display: none;
}
#mocha-report.pending .test.pass.pending {
display: block;
}
#mocha-error {
color: #c00;
font-size: 1.5em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
z-index: 1;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}