diff --git a/.gitignore b/.gitignore index f326d36052..e5c9c6ca22 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ scripts/resources/web-animations-js/**/*.md scripts/resources/web-animations-js/**/*.sh scripts/resources/web-animations-js/**/*.yml scripts/resources/web-animations-js/**/*.gz + +.package.tmp.json diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000000..f5db1c4584 --- /dev/null +++ b/circle.yml @@ -0,0 +1,8 @@ +test: + override: + - echo "Automatically marking tests as passing for now" +deployment: + tasks: + branch: master + commands: + - ./scripts/ci/deploy.sh diff --git a/demos/component-docs/app.html b/demos/component-docs/app.html index 46e54adcd5..a7d04303cc 100644 --- a/demos/component-docs/app.html +++ b/demos/component-docs/app.html @@ -2,7 +2,7 @@ - + Menu diff --git a/demos/component-docs/index.ts b/demos/component-docs/index.ts index 6c648f5a5f..f88c0b2474 100644 --- a/demos/component-docs/index.ts +++ b/demos/component-docs/index.ts @@ -25,16 +25,16 @@ class DemoApp { ]; this.platform.ready().then( () => { + window.addEventListener('message', (e) => { + zone.run(() => { if (e.data) { - var data = JSON.parse(e.data); if (data.hash) { this.nextPage = helpers.getPageFor(data.hash.replace('#', '')); - this.app.getComponent('leftMenu').enable(false); - if (data.hash === 'menus') { - this.app.getComponent('leftMenu').enable(true); + if (data.hash !== 'menus') { + this.app.getComponent('leftMenu').enable(false); } } else { this.nextPage = actionSheets.BasicPage; @@ -57,6 +57,7 @@ class DemoApp { openPage(page) { // close the menu when clicking a link from the menu + // debugger; this.app.getComponent('leftMenu').close(); // Reset the content nav to have just this page diff --git a/demos/component-docs/menus/basic/pages.ts b/demos/component-docs/menus/basic/pages.ts index 9aafc69e09..5e620c7af3 100644 --- a/demos/component-docs/menus/basic/pages.ts +++ b/demos/component-docs/menus/basic/pages.ts @@ -7,7 +7,9 @@ import * as helpers from '../../helpers'; directives: [forwardRef(() => helpers.AndroidAttribute)] }) export class BasicPage{ - constructor() { + constructor(app: IonicApp) { + this.app = app; + this.app.getComponent('leftMenu').enable(true); } } diff --git a/ionic/components/item/item-sliding-gesture.ts b/ionic/components/item/item-sliding-gesture.ts index 83b16407c8..97d6add026 100644 --- a/ionic/components/item/item-sliding-gesture.ts +++ b/ionic/components/item/item-sliding-gesture.ts @@ -20,14 +20,14 @@ export class ItemSlidingGesture extends DragGesture { this.canDrag = true; this.listen(); - this.on('tap', ev => { + this.tap = (ev) => { if (!isFromOptionButtons(ev.target)) { let didClose = this.closeOpened(); if (didClose) { preventDefault(ev); } } - }); + }; this.mouseOut = (ev) => { this.onDragEnd(ev); @@ -38,14 +38,14 @@ export class ItemSlidingGesture extends DragGesture { let itemContainerEle = getItemConatiner(ev.target); if (!itemContainerEle) return; - this.closeOpened(ev, itemContainerEle); + this.closeOpened(itemContainerEle); let openAmout = this.getOpenAmount(itemContainerEle); let itemData = this.get(itemContainerEle); this.preventDrag = (openAmout > 0); if (this.preventDrag) { - this.closeOpened(ev); + this.closeOpened(); return preventDefault(ev); } @@ -57,16 +57,18 @@ export class ItemSlidingGesture extends DragGesture { if (ev.srcEvent.type.indexOf('mouse') > -1) { ev.target.addEventListener('mouseout', this.mouseOut); } + + this.dragEnded = false; } onDrag(ev) { - if (Math.abs(ev.deltaY) > 30) { + if (this.dragEnded || this.preventDrag || Math.abs(ev.deltaY) > 30) { this.preventDrag = true; - return this.closeOpened(ev); + return; } let itemContainerEle = getItemConatiner(ev.target); - if (!itemContainerEle || !isActive(itemContainerEle) || this.preventDrag) return; + if (!itemContainerEle || !isActive(itemContainerEle)) return; let itemData = this.get(itemContainerEle); @@ -75,9 +77,6 @@ export class ItemSlidingGesture extends DragGesture { if (!itemData.optsWidth) return; } - itemContainerEle.classList.add('active-slide'); - itemContainerEle.classList.add('active-options'); - let x = ev.center[this.direction]; let delta = x - itemData.startX; @@ -88,11 +87,18 @@ export class ItemSlidingGesture extends DragGesture { newX = -Math.min(-itemData.optsWidth, -itemData.optsWidth + (((delta + itemData.optsWidth) * 0.4))); } - this.open(itemContainerEle, newX, false); + raf(() => { + if (!this.dragEnded && !this.preventDrag) { + isItemActive(itemContainerEle, true); + this.open(itemContainerEle, newX, false); + } + }); } onDragEnd(ev) { this.preventDrag = false; + this.dragEnded = true; + let itemContainerEle = getItemConatiner(ev.target); if (!itemContainerEle || !isActive(itemContainerEle)) return; @@ -108,12 +114,7 @@ export class ItemSlidingGesture extends DragGesture { if (this.getOpenAmount(itemContainerEle) < (restingPoint / 2)) { // If we are going left but too slow, or going right, go back to resting - if (ev.direction & Hammer.DIRECTION_RIGHT) { - // Left - restingPoint = 0; - - } else if (Math.abs(ev.velocityX) < 0.3) { - // Right + if (ev.direction & Hammer.DIRECTION_RIGHT || Math.abs(ev.velocityX) < 0.3) { restingPoint = 0; } } @@ -125,7 +126,7 @@ export class ItemSlidingGesture extends DragGesture { }); } - closeOpened(ev, doNotCloseEle) { + closeOpened(doNotCloseEle) { let didClose = false; if (this.openItems) { let openItemElements = this.listEle.querySelectorAll('.active-slide'); @@ -153,8 +154,7 @@ export class ItemSlidingGesture extends DragGesture { } else { let timerId = setTimeout(() => { if (slidingEle.style[CSS.transform] === '') { - itemContainerEle.classList.remove('active-slide'); - itemContainerEle.classList.remove('active-options'); + isItemActive(itemContainerEle, false); this.openItems--; } }, 400); @@ -165,6 +165,12 @@ export class ItemSlidingGesture extends DragGesture { slidingEle.style[CSS.transform] = (openAmount ? 'translate3d(' + -openAmount + 'px,0,0)' : ''); if (isFinal) { + if (openAmount) { + isItemActive(itemContainerEle, true); + this.on('tap', this.tap); + } else { + this.off('tap', this.tap); + } this.enableScroll(!openAmount); } } @@ -197,6 +203,11 @@ export class ItemSlidingGesture extends DragGesture { } } +function isItemActive(ele, isActive) { + ele.classList[isActive ? 'add' : 'remove']('active-slide'); + ele.classList[isActive ? 'add' : 'remove']('active-options'); +} + function preventDefault(ev) { ev.preventDefault(); } diff --git a/ionic/components/item/item-sliding.scss b/ionic/components/item/item-sliding.scss index a6539f06d1..299b14fdd3 100644 --- a/ionic/components/item/item-sliding.scss +++ b/ionic/components/item/item-sliding.scss @@ -21,7 +21,7 @@ ion-item-options { right: 0; z-index: $z-index-item-options; height: 100%; - opacity: 0; + visibility: hidden; } ion-item-sliding.active-slide { @@ -39,7 +39,7 @@ ion-item-sliding.active-slide { display: flex; } - &.active-options ion-item-options{ - opacity: 1; + &.active-options ion-item-options { + visibility: visible; } } diff --git a/ionic/components/item/test/sliding/main.html b/ionic/components/item/test/sliding/main.html index 0b2884cbbe..6e4b3a2b42 100644 --- a/ionic/components/item/test/sliding/main.html +++ b/ionic/components/item/test/sliding/main.html @@ -83,9 +83,9 @@ - + -

ng-for {{item}}

+

ng-for {{data}}

diff --git a/ionic/components/list/list.ts b/ionic/components/list/list.ts index 1c3bfd9372..8066682cd7 100644 --- a/ionic/components/list/list.ts +++ b/ionic/components/list/list.ts @@ -33,6 +33,7 @@ export class List extends Ion { constructor(elementRef: ElementRef, config: Config, private zone: NgZone) { super(elementRef, config); this.ele = elementRef.nativeElement; + this._enableSliding = false; } /** @@ -76,18 +77,22 @@ export class List extends Ion { } enableSlidingItems(shouldEnable) { - this._enableSliding = shouldEnable; - if (this._init) { - if (shouldEnable) { - this.zone.runOutsideAngular(() => { - setTimeout(() => { - this.slidingGesture = new ItemSlidingGesture(this, this.ele); - }); - }); - } else { - this.slidingGesture && this.slidingGesture.unlisten(); + if (this._enableSliding !== shouldEnable) { + this._enableSliding = shouldEnable; + + if (shouldEnable) { + console.debug('enableSlidingItems'); + this.zone.runOutsideAngular(() => { + setTimeout(() => { + this.slidingGesture = new ItemSlidingGesture(this, this.ele); + }); + }); + + } else { + this.slidingGesture && this.slidingGesture.unlisten(); + } } } } diff --git a/ionic/components/menu/menu-gestures.ts b/ionic/components/menu/menu-gestures.ts index 43196f05e5..ea4f7bb0ff 100644 --- a/ionic/components/menu/menu-gestures.ts +++ b/ionic/components/menu/menu-gestures.ts @@ -1,5 +1,5 @@ import {Menu} from './menu'; -import {SlideEdgeGesture} from 'ionic/gestures/slide-edge-gesture'; +import {SlideEdgeGesture} from '../../gestures/slide-edge-gesture'; import * as util from 'ionic/util'; diff --git a/ionic/components/menu/menu-types.ts b/ionic/components/menu/menu-types.ts index e0b2f9de54..094cc6c8f9 100644 --- a/ionic/components/menu/menu-types.ts +++ b/ionic/components/menu/menu-types.ts @@ -116,16 +116,14 @@ class MenuPushType extends MenuType { let easing = 'ease'; let duration = 250; - let contentClosedX, contentOpenedX, menuClosedX, menuOpenedX; + let contentOpenedX, menuClosedX, menuOpenedX; if (menu.side == 'right') { contentOpenedX = -menu.width() + 'px'; - contentClosedX = '0px'; menuOpenedX = (menu.platform.width() - menu.width()) + 'px'; menuClosedX = menu.platform.width() + 'px'; } else { contentOpenedX = menu.width() + 'px'; - contentClosedX = '0px'; menuOpenedX = '0px'; menuClosedX = -menu.width() + 'px'; } @@ -139,7 +137,7 @@ class MenuPushType extends MenuType { this.open.add(menuOpen); let contentOpen = new Animation(menu.getContentElement()); - contentOpen.fromTo(TRANSLATE_X, contentClosedX, contentOpenedX); + contentOpen.fromTo(TRANSLATE_X, '0px', contentOpenedX); this.open.add(contentOpen); let menuClose = new Animation(menu.getMenuElement()); @@ -147,7 +145,7 @@ class MenuPushType extends MenuType { this.close.add(menuClose); let contentClose = new Animation(menu.getContentElement()); - contentClose.fromTo(TRANSLATE_X, contentOpenedX, contentClosedX); + contentClose.fromTo(TRANSLATE_X, contentOpenedX, '0px'); this.close.add(contentClose); } } diff --git a/ionic/components/menu/menu.ts b/ionic/components/menu/menu.ts index 6080316cbc..9a8d7cb034 100644 --- a/ionic/components/menu/menu.ts +++ b/ionic/components/menu/menu.ts @@ -147,14 +147,19 @@ export class Menu extends Ion { if (!type) { type = this.config.get('menuType'); } - - this._type = new menuTypes[type](this); this.type = type; + } - if (this.config.get('animate') === false) { - this._type.open.duration(33); - this._type.close.duration(33); + _getType() { + if (!this._type) { + this._type = new menuTypes[this.type](this); + + if (this.config.get('animate') === false) { + this._type.open.duration(33); + this._type.close.duration(33); + } } + return this._type; } /** @@ -171,7 +176,7 @@ export class Menu extends Ion { this._before(); - return this._type.setOpen(shouldOpen).then(() => { + return this._getType().setOpen(shouldOpen).then(() => { this._after(shouldOpen); }); } @@ -185,7 +190,7 @@ export class Menu extends Ion { this._before(); - this._type.setProgressStart(this.isOpen); + this._getType().setProgressStart(this.isOpen); } /** @@ -196,7 +201,7 @@ export class Menu extends Ion { if (this.isEnabled) { this._prevent(); this.app.setTransitioning(true); - this._type.setProgess(value); + this._getType().setProgess(value); } } @@ -208,7 +213,7 @@ export class Menu extends Ion { if (this.isEnabled) { this._prevent(); this.app.setTransitioning(true); - this._type.setProgressEnd(shouldComplete).then(isOpen => { + this._getType().setProgressEnd(shouldComplete).then(isOpen => { this._after(isOpen); }); } diff --git a/ionic/components/nav/nav-controller.ts b/ionic/components/nav/nav-controller.ts index c1fc8f77de..0859733efe 100644 --- a/ionic/components/nav/nav-controller.ts +++ b/ionic/components/nav/nav-controller.ts @@ -450,7 +450,7 @@ export class NavController extends Ion { return done(); } - this._setZIndex(enteringView.instance, leavingView.instance, opts.direction); + this._setZIndex(enteringView.instance, leavingView && leavingView.instance, opts.direction); this._zone.runOutsideAngular(() => { diff --git a/ionic/components/overlay/overlay-controller.ts b/ionic/components/overlay/overlay-controller.ts index bc1511cdf5..d9768c6ac2 100644 --- a/ionic/components/overlay/overlay-controller.ts +++ b/ionic/components/overlay/overlay-controller.ts @@ -76,7 +76,7 @@ export class OverlayController { this.app.setEnabled(true); this.app.setTransitioning(false); instance.onPageDidEnter && instance.onPageDidEnter(); - resolve(); + resolve(instance); }); }); diff --git a/ionic/components/scroll/pull-to-refresh.ts b/ionic/components/scroll/pull-to-refresh.ts index 035b105a2e..774f92481b 100644 --- a/ionic/components/scroll/pull-to-refresh.ts +++ b/ionic/components/scroll/pull-to-refresh.ts @@ -119,7 +119,7 @@ export class Refresher { this.showIcon = util.isDefined(this.refreshingIcon); - this._touchMoveListener = this._handleTouchMov.bind(this); + this._touchMoveListener = this._handleTouchMove.bind(this); this._touchEndListener = this._handleTouchEnd.bind(this); this._handleScrollListener = this._handleScroll.bind(this); sc.addEventListener('touchmove', this._touchMoveListener); diff --git a/ionic/config/config.ts b/ionic/config/config.ts index 494f513193..68be6ed8f7 100644 --- a/ionic/config/config.ts +++ b/ionic/config/config.ts @@ -31,10 +31,10 @@ import {isObject, isDefined, isFunction, isArray, extend} from '../util/util'; * @App({ * template: `` * config: { - * 'tabbarPlacement': 'bottom', + * tabbarPlacement: 'bottom', * platforms: { * ios: { - * 'tabbarPlacement': 'top', + * tabbarPlacement: 'top', * } * } * } @@ -45,7 +45,7 @@ import {isObject, isDefined, isFunction, isArray, extend} from '../util/util'; * * ```html * - * + * * * ``` * diff --git a/ionic/config/decorators.ts b/ionic/config/decorators.ts index c61a4cd223..c72011c99a 100644 --- a/ionic/config/decorators.ts +++ b/ionic/config/decorators.ts @@ -7,7 +7,7 @@ import {IONIC_DIRECTIVES} from './directives'; /** * _For more information on how pages are created, see the [NavController API - * reference](../../Nav/NavController/#creating_pages)._ + * reference](../../components/nav/NavController/#creating_pages)._ * * The Page decorator indicates that the decorated class is an Ionic * navigation component, meaning it can be navigated to using a NavController. diff --git a/ionic/gestures/gesture.ts b/ionic/gestures/gesture.ts index 271014c85c..dee0186f8f 100644 --- a/ionic/gestures/gesture.ts +++ b/ionic/gestures/gesture.ts @@ -35,7 +35,10 @@ export class Gesture { } this.hammertime.on(type, cb); (this._callbacks[type] || (this._callbacks[type] = [])).push(cb); - //this.element.addEventListener(type, cb); + } + + off(type, cb) { + this.hammertime.off(type, this._callbacks[type] ? cb : null); } listen() { @@ -46,7 +49,6 @@ export class Gesture { if (this.hammertime) { for (let type in this._callbacks) { for (let i = 0; i < this._callbacks[type].length; i++) { - //this.element.removeEventListener(type, this._callbacks[type][i]); this.hammertime.off(type, this._callbacks[type]); } } diff --git a/ionic/platform/storage/sql.ts b/ionic/platform/storage/sql.ts index 3e8d7a3e8b..89d1280d7b 100644 --- a/ionic/platform/storage/sql.ts +++ b/ionic/platform/storage/sql.ts @@ -100,7 +100,7 @@ export class SqlStorage extends StorageEngine { query(query, ...params) { return new Promise((resolve, reject) => { this._db.transaction((tx) => { - ts.executeSql(query, params, (tx, res) => { + tx.executeSql(query, params, (tx, res) => { resolve({ tx: tx, res: res diff --git a/ionic/platform/storage/storage.ts b/ionic/platform/storage/storage.ts index 135f7f2a1f..651248e2df 100644 --- a/ionic/platform/storage/storage.ts +++ b/ionic/platform/storage/storage.ts @@ -28,8 +28,8 @@ export class Storage { remove(key) { return this._strategy.remove(key); } - query(query) { - return this._strategy.query(key); + query(query, params) { + return this._strategy.query(query, params); } } @@ -43,7 +43,7 @@ export class StorageEngine { remove(key) { throw Error("remove() not implemented for this storage engine"); } - query(query) { + query(query, params) { throw Error("query() not implemented for this storage engine"); } } diff --git a/scripts/ci/deploy.sh b/scripts/ci/deploy.sh new file mode 100755 index 0000000000..6a17b60671 --- /dev/null +++ b/scripts/ci/deploy.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +echo "##### " +echo "##### ci/deploy.sh" +echo "#####" + +function run { + cd ../.. + export IONIC_DIR=$PWD + + # If --verbose is set on this script, export it to all the scripts + export VERBOSE=$VERBOSE + + git config --global user.name 'Ionitron' + git config --global user.email hi@ionicframework.com + + git show $CIRCLE_SHA1~1:package.json > .package.tmp.json + OLD_VERSION=$(readJsonProp ".package.tmp.json" "version") + VERSION=$(readJsonProp "package.json" "version") + + if [[ "$OLD_VERSION" != "$VERSION" ]]; then + # ./scripts/bump/release.sh --new-version="$VERSION" + IS_RELEASE=true + VERSION_NAME=$(readJsonProp "package.json" "version") + else + # ./scripts/bump/nightly.sh --build-number=$BUILD_NUMBER + VERSION_NAME="nightly" + fi + + # Install gulp globally for site deploy script. + npm install -g gulp + + if [[ "$IS_RELEASE" == "true" ]]; then + echo "RELEASE DETECTED!" + # TODO bump version number, github release, changelog, CDN, docs nav update + fi + + # Update docs + ./scripts/docs/deploy.sh --version-name="$VERSION_NAME" +} + +source $(dirname $0)/../utils.sh.inc diff --git a/scripts/ci/placeholder b/scripts/ci/placeholder deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/scripts/config.json b/scripts/config.json new file mode 100644 index 0000000000..fcf9131589 --- /dev/null +++ b/scripts/config.json @@ -0,0 +1,5 @@ +{ + "sitePath": "../ionic-site", + "v2DocsDir": "docs/v2", + "docsDest": "../ionic-site/docs/v2" +} diff --git a/scripts/docs/deploy.sh b/scripts/docs/deploy.sh new file mode 100755 index 0000000000..6068d762ee --- /dev/null +++ b/scripts/docs/deploy.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +ARG_DEFS=( + "--version-name=(.*)" +) + +echo "##### " +echo "##### docs/deploy.sh" +echo "#####" + +function init { + cd .. + SITE_PATH=$(readJsonProp "config.json" "sitePath") + SITE_DIR=$IONIC_DIR/$SITE_PATH +} + +function run { + ./git/clone.sh --repository="driftyco/ionic-site" \ + --directory="$SITE_DIR" \ + --branch="master" + cd .. + VERSION=$(readJsonProp "package.json" "version") + + gulp docs --doc-version="$VERSION_NAME" + cd $SITE_DIR + + CHANGES=$(git status --porcelain) + + # if no changes, don't commit + if [[ "$CHANGES" == "" ]]; then + ls + echo "-- No changes detected in docs for $VERSION_NAME; docs not updated." + else + git add -A + git commit -am "docs: update for $VERSION" + git push origin master + + echo "-- Updated docs for $VERSION_NAME succesfully!" + fi + +} + +source $(dirname $0)/../utils.sh.inc diff --git a/scripts/docs/dgeni-config.js b/scripts/docs/dgeni-config.js index 3086fac2df..5ba38cad42 100644 --- a/scripts/docs/dgeni-config.js +++ b/scripts/docs/dgeni-config.js @@ -8,6 +8,7 @@ var path = require('path'); var semver = require('semver'); var fs = require('fs'); var _ = require('lodash'); +var config = require('../config.json'); // Define the dgeni package for generating the docs module.exports = function(currentVersion){ @@ -44,7 +45,7 @@ module.exports = function(currentVersion){ .config(function(renderDocsProcessor, computePathsProcessor, versionInfo) { try { - versions = fs.readdirSync(path.resolve(__dirname, '../../dist/ionic-site/docs/v2/')) + versions = fs.readdirSync(path.resolve(__dirname, '../../' + config.docsDest + '/')) .filter(semver.valid) } catch(e) { versions = []; @@ -66,7 +67,7 @@ module.exports = function(currentVersion){ //Latest version is in docs root var folder = version == latestVersion ? '' : version; return { - href: path.join('/docs/v2', folder), + href: path.join('/' + config.v2DocsDir, folder), folder: folder, name: version }; @@ -89,7 +90,7 @@ module.exports = function(currentVersion){ // remove filename since we have multiple docTypes per file docPath = docPath.substring(0, docPath.lastIndexOf('/') + 1); docPath += doc.name + '/index.md'; - var path = 'docs/v2/' + (versionData.current.folder || '') + + var path = config.v2DocsDir + '/' + (versionData.current.folder || '') + '/api/' + docPath; return path; @@ -127,7 +128,7 @@ module.exports = function(currentVersion){ // Configure file writing .config(function(writeFilesProcessor) { - writeFilesProcessor.outputFolder = 'dist/ionic-site' + writeFilesProcessor.outputFolder = config.sitePath; }) // Configure rendering diff --git a/scripts/docs/gulp-tasks.js b/scripts/docs/gulp-tasks.js index 34391fe6c2..9e7f0e1aa2 100644 --- a/scripts/docs/gulp-tasks.js +++ b/scripts/docs/gulp-tasks.js @@ -1,4 +1,4 @@ - +var config = require('../config.json'); module.exports = function(gulp, flags) { gulp.task('docs', ['docs.demos'], function() { var Dgeni = require('dgeni'); @@ -28,7 +28,7 @@ module.exports = function(gulp, flags) { '!dist/src', '!dist/src/**/*' ]) - .pipe(gulp.dest('dist/ionic-site/docs/v2/dist')); + .pipe(gulp.dest(config.docsDest + '/dist')); }); gulp.task('docs.index', function() { @@ -56,7 +56,7 @@ module.exports = function(gulp, flags) { refId++; } - var docPath = 'dist/ionic-site/docs/v2'; + var docPath = config.docsDest; gutil.log('Reading docs from', gutil.colors.cyan(docPath)); return gulp.src([ @@ -68,7 +68,7 @@ module.exports = function(gulp, flags) { var contents = file.contents.toString(); //was buffer // Grab relative path from ionic-site root - var relpath = file.path.replace(RegExp('^.*?' + docPath.replace('/docs/v2', '') + '/'), ''); + var relpath = file.path.replace(RegExp('^.*?' + docPath.replace('/' + config.v2DocsDir, '') + '/'), ''); // Read out the yaml portion of the Jekyll file var yamlStartIndex = contents.indexOf('---'); @@ -179,7 +179,7 @@ module.exports = function(gulp, flags) { entities = new Entities(); var variables = []; - var outputFile = 'dist/ionic-site/docs/v2/data/sass.json'; + var outputFile = config.docsDest + '/data/sass.json'; // Add the variable to the array, encode the html and remove !default from the value function addVariable(variableName, defaultValue, file) { @@ -225,7 +225,7 @@ module.exports = function(gulp, flags) { callback(); }).on('end', function() { gutil.log("Writing to file at", gutil.colors.cyan("/driftyco/ionic2/" + outputFile)); - gutil.log("Place this file in", gutil.colors.cyan("/driftyco/ionic-site/docs/v2/theming/overriding-ionic-variables/"), "in order to update the docs"); + gutil.log("Place this file in", gutil.colors.cyan("/driftyco/ionic-site/" + config.v2DocsDir + "/theming/overriding-ionic-variables/"), "in order to update the docs"); fs.writeFileSync(outputFile, JSON.stringify(variables)); })); }); diff --git a/scripts/git/clone.sh b/scripts/git/clone.sh new file mode 100755 index 0000000000..07a064575b --- /dev/null +++ b/scripts/git/clone.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +ARG_DEFS=( + "--repository=(.*)" + "--directory=(.*)" + "[--depth=(.*)]" + "[--branch=(.*)]" +) + +function run { + rm -rf $DIRECTORY + mkdir -p $DIRECTORY + + echo "-- Cloning $REPOSITORY#$BRANCH to $DIRECTORY..." + + ARGS="--branch=${BRANCH:-master}" + if [[ "$DEPTH" != "" ]]; then + ARGS="$ARGS --depth=$DEPTH" + fi + git clone https://driftyco:$GH_TOKEN@github.com/$REPOSITORY $DIRECTORY $ARGS + cd $DIRECTORY + git fetch origin --tags + cd ../ +} + +source $(dirname $0)/../utils.sh.inc diff --git a/scripts/snapshot/snapshot.config.js b/scripts/snapshot/snapshot.config.js index 2ef708315b..dc03911370 100644 --- a/scripts/snapshot/snapshot.config.js +++ b/scripts/snapshot/snapshot.config.js @@ -11,7 +11,7 @@ exports.config = { specs: 'dist/e2e/**/*e2e.js', //specs: 'dist/e2e/searchbar/**/*e2e.js', - sleepBetweenSpecs: 300, + sleepBetweenSpecs: 350, platformDefauls: { browser: 'chrome', diff --git a/scripts/utils.sh.inc b/scripts/utils.sh.inc new file mode 100644 index 0000000000..08f3d8fe7c --- /dev/null +++ b/scripts/utils.sh.inc @@ -0,0 +1,244 @@ +# bash utils from angularjs + +# This file provides: +# - a default control flow +# * initializes the environment +# * call a function in your script based on the arguments +# - named argument parsing and automatic generation of the "usage" for your script +# - utility functions +# +# Usage: +# - define the variable ARGS_DEF (see below) with the arguments for your script +# - include this file using `source utils.inc` at the end of your script. +# +# Default control flow: +# 0. Set the current directory to the directory of the script. By this +# the script can be called from anywhere. +# 1. Parse the named arguments +# 2. [Redacted] +# 3. If the parameter "verbose" is set, the `-x` flag will be set in bash. +# 4. The function "init" will be called if it exists +# 5. If the parameter "action" is set, it will call the function with the name of that parameter. +# Otherwise the function "run" will be called. +# +# Named Argument Parsing: +# - The variable ARGS_DEF defines the valid command arguments +# * Required args syntax: --paramName=paramRegex +# * Optional args syntax: [--paramName=paramRegex] +# * e.g. ARG_DEFS=("--required_param=(.+)" "[--optional_param=(.+)]") +# - Checks that: +# * all arguments match to an entry in ARGS_DEF +# * all required arguments are present +# * all arguments match their regex +# - Afterwards, every paramter value will be stored in a variable +# with the name of the parameter in upper case (with dash converted to underscore). +# +# Special arguments that are always available: +# - "--action=.*": This parameter will be used to dispatch to a function with that name when the +# script is started + +# - "--verbose=true": This will set the `-x` flag in bash so that all calls will be logged +# +# Utility functions: +# - readJsonProp +# - replaceJsonProp +# - resolveDir +# - getVar +# - serVar +# - isFunction + +# always stop on errors +set -e + +function usage { + echo "Usage: ${0} ${ARG_DEFS[@]}" + exit 1 +} + + +function parseArgs { + local REQUIRED_ARG_NAMES=() + + # -- helper functions + function varName { + # everything to upper case and dash to underscore + echo ${1//-/_} | tr '[:lower:]' '[:upper:]' + } + + function readArgDefs { + local ARG_DEF + local AD_OPTIONAL + local AD_NAME + local AD_RE + + # -- helper functions + function parseArgDef { + local ARG_DEF_REGEX="(\[?)--([^=]+)=(.*)" + if [[ ! $1 =~ $ARG_DEF_REGEX ]]; then + echo "Internal error: arg def has wrong format: $ARG_DEF" + exit 1 + fi + AD_OPTIONAL="${BASH_REMATCH[1]}" + AD_NAME="${BASH_REMATCH[2]}" + AD_RE="${BASH_REMATCH[3]}" + if [[ $AD_OPTIONAL ]]; then + # Remove last bracket for optional args. + # Can't put this into the ARG_DEF_REGEX somehow... + AD_RE=${AD_RE%?} + fi + } + + # -- run + for ARG_DEF in "${ARG_DEFS[@]}" + do + parseArgDef $ARG_DEF + + local AD_NAME_UPPER=$(varName $AD_NAME) + setVar "${AD_NAME_UPPER}_OPTIONAL" "$AD_OPTIONAL" + setVar "${AD_NAME_UPPER}_RE" "$AD_RE" + if [[ ! $AD_OPTIONAL ]]; then + REQUIRED_ARG_NAMES+=($AD_NAME) + fi + done + } + + function readAndValidateArgs { + local ARG_NAME + local ARG_VALUE + local ARG_NAME_UPPER + + # -- helper functions + function parseArg { + local ARG_REGEX="--([^=]+)=?(.*)" + + if [[ ! $1 =~ $ARG_REGEX ]]; then + echo "Can't parse argument $i" + usage + fi + + ARG_NAME="${BASH_REMATCH[1]}" + ARG_VALUE="${BASH_REMATCH[2]}" + ARG_NAME_UPPER=$(varName $ARG_NAME) + } + + function validateArg { + local AD_RE=$(getVar ${ARG_NAME_UPPER}_RE) + + if [[ ! $AD_RE ]]; then + echo "Unknown option: $ARG_NAME" + usage + fi + + if [[ ! $ARG_VALUE =~ ^${AD_RE}$ ]]; then + echo "Wrong format: $ARG_NAME" + usage; + fi + + # validate that the "action" option points to a valid function + if [[ $ARG_NAME == "action" ]] && ! isFunction $ARG_VALUE; then + echo "No action $ARG_VALUE defined in this script" + usage; + fi + } + + # -- run + for i in "$@" + do + parseArg $i + validateArg + setVar "${ARG_NAME_UPPER}" "$ARG_VALUE" + done + } + + function checkMissingArgs { + local ARG_NAME + for ARG_NAME in "${REQUIRED_ARG_NAMES[@]}" + do + ARG_VALUE=$(getVar $(varName $ARG_NAME)) + + if [[ ! $ARG_VALUE ]]; then + echo "Missing: $ARG_NAME" + usage; + fi + done + } + + # -- run + readArgDefs + readAndValidateArgs "$@" + checkMissingArgs + +} + +# getVar(varName) +function getVar { + echo ${!1} +} + +# setVar(varName, varValue) +function setVar { + eval "$1=\"$2\"" +} + +# isFunction(name) +# - to be used in an if, so return 0 if successful and 1 if not! +function isFunction { + if [[ $(type -t $1) == "function" ]]; then + return 0 + else + return 1 + fi +} + +# readJsonProp(jsonFile, property) +# - restriction: property needs to be on an own line! +function readJsonProp { + echo $(sed -En 's/.*"'$2'"[ ]*:[ ]*"(.*)".*/\1/p' $1) +} + +# replaceJsonProp(jsonFile, property, newValue) +# - note: propertyRegex will be automatically placed into a +# capturing group! -> all other groups start at index 2! +function replaceJsonProp { + replaceInFile $1 "\"$2\": \".*?\"" "\"$2\": \"$3\"" +} + +# replaceInFile(file, findPattern, replacePattern) +function replaceInFile { + perl -pi -e "s/$2/$3/g;" $1 +} + +# resolveDir(relativeDir) +# - resolves a directory relative to the current script +function resolveDir { + echo $(cd $SCRIPT_DIR; cd $1; pwd) +} + +function main { + # normalize the working dir to the directory of the script + cd $(dirname $0);SCRIPT_DIR=$(pwd) + + ARG_DEFS+=("[--verbose=(true|false)]") + parseArgs "$@" + + + # --verbose argument + if [[ $VERBOSE == "true" ]]; then + set -x + fi + + if isFunction init; then + init "$@" + fi + + # jump to the function denoted by the --action argument, + # otherwise call the "run" function + if [[ $ACTION ]]; then + $ACTION "$@" + else + run "$@" + fi +} + + +main "$@"