chore(demos): update demos to work

* chore(demos): WIP refactor gulp demos task to use SystemJS

move build files into dist/demos and comment out the AoT demos task for
right now. This makes both `gulp demos` and `gulp demos.watch`work
again.

references #8411

* docs(demos): fix infinite scroll demo

* chore(demos): move old demos task to demos.prod

update the demos file with shared tasks, include the shared css

* docs(demos): fix API demos to use correct styles

* chore(demos): remove the main.ts files from each demo

* chore(demos): add prod template and constant

* chore(demos): remove tsconfig and package from demos

* chore(demos): update app.module path to ionic

* chore(demos): update app.module path to ionic

* chore(demos): update prod task for demos to work with AoT

also puts the demo build files into dist/ instead of the src directory

* docs(demos): update deploy and docs tasks for new build

* docs(scripts): update demos README

* chore(demos): fix path for prod build
This commit is contained in:
Brandy Carney
2016-12-13 13:56:22 -05:00
committed by Adam Bradley
parent 3701ee5e37
commit 1f83cde78b
182 changed files with 2946 additions and 3626 deletions

View File

@ -23,6 +23,8 @@ export const PROJECT_ROOT = join(__dirname, '../..');
export const DEMOS_ROOT = join(PROJECT_ROOT, DEMOS_NAME);
export const DEMOS_SRC_ROOT = join(DEMOS_ROOT, SRC_NAME);
export const DIST_ROOT = join(PROJECT_ROOT, DIST_NAME);
export const DIST_DEMOS_ROOT = join(DIST_ROOT, DEMOS_NAME);
export const DIST_DEMOS_COMPONENTS_ROOT = join(DIST_DEMOS_ROOT, COMPONENTS_NAME);
export const DIST_E2E_ROOT = join(DIST_ROOT, E2E_NAME);
export const DIST_E2E_COMPONENTS_ROOT = join(DIST_E2E_ROOT, COMPONENTS_NAME);
export const DIST_BUILD_ROOT = join(DIST_ROOT, PACKAGE_NAME);

View File

@ -2,6 +2,8 @@ import './tasks/build';
import './tasks/clean';
import './tasks/default';
import './tasks/demos';
import './tasks/demos.dev';
import './tasks/demos.prod';
import './tasks/docs';
import './tasks/e2e';
import './tasks/e2e.dev';

View File

@ -0,0 +1,187 @@
import { readFileSync } from 'fs';
import { dirname, join } from 'path';
import { dest, src, start, task } from 'gulp';
import * as babel from 'gulp-babel';
import * as cache from 'gulp-cached';
import * as concat from 'gulp-concat';
import * as connect from 'gulp-connect';
import * as gulpif from 'gulp-if';
import * as remember from 'gulp-remember';
import * as tsc from 'gulp-typescript';
import * as watch from 'gulp-watch';
import { template } from 'lodash';
import * as merge from 'merge2';
import * as runSequence from 'run-sequence';
import { obj } from 'through2';
import * as VinylFile from 'vinyl';
import { DEMOS_NAME, DIST_DEMOS_ROOT, DIST_NAME, ES5, ES_2015, SCRIPTS_ROOT } from '../constants';
const buildConfig = require('../../build/config');
/**
* Builds Ionic demos tests to dist/demos and creates the necessary files for tests
* to run.
*/
task('demos', demosBuild);
function demosBuild(done: (err: any) => void) {
runSequence(
'demos.clean',
'demos.build',
'demos.polyfill',
'demos.copyExternalDependencies',
'demos.sass',
'demos.fonts',
'demos.bundle',
done);
}
/**
* Builds Ionic demos tests to dist/demos.
*/
task('demos.build', function () {
var indexTemplate = template(
readFileSync(`${SCRIPTS_ROOT}/${DEMOS_NAME}/demos.template.dev.html`).toString()
)({
buildConfig: buildConfig
});
// Get each test folder with src
var tsResult = src([
'demos/src/*/**/*.ts'
])
.pipe(cache('demos.ts'))
.pipe(tsc(getTscOptions(), undefined, tscReporter))
.on('error', function (error) {
console.log(error.message);
})
.pipe(gulpif(/app.module.js$/, createIndexHTML()));
var testFiles = src([
'demos/src/*/**/*',
'!demos/src/*/**/*.ts'
])
.pipe(cache('demos.files'));
return merge([
tsResult,
testFiles
])
.pipe(dest(DIST_DEMOS_ROOT))
.pipe(connect.reload());
function createIndexHTML() {
return obj(function (file, enc, next) {
this.push(new VinylFile({
base: file.base,
contents: new Buffer(indexTemplate),
path: join(dirname(file.path), 'index.html'),
}));
next(null, file);
});
}
});
/**
* Creates SystemJS bundle from Ionic source files.
*/
task('demos.bundle', function () {
var tsResult = tsCompile(getTscOptions('es6'), 'system')
.pipe(babel(babelOptions));
var swiper = src('src/components/slides/swiper-widget.system.js');
return merge([tsResult, swiper])
.pipe(remember('system'))
.pipe(concat('ionic.system.js'))
.pipe(dest(`${DIST_NAME}/bundles`))
.pipe(connect.reload());
});
function tsCompile(options, cacheName) {
return src([
'typings/main.d.ts',
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/components/*/test/**/*',
'!src/util/test/*',
'!src/config/test/*',
'!src/platform/test/*',
'!src/**/*.spec.ts'
])
.pipe(cache(cacheName, { optimizeMemory: true }))
.pipe(tsc(options, undefined, tscReporter));
}
function getTscOptions(name?: string) {
var opts = {
emitDecoratorMetadata: true,
experimentalDecorators: true,
target: ES5,
module: 'commonjs',
isolatedModules: true,
typescript: require('typescript'),
declaration: false
};
if (name === 'typecheck') {
opts.declaration = true;
delete opts.isolatedModules;
} else if (name === 'es6') {
opts.target = 'es6';
delete opts.module;
}
return opts;
}
var tscReporter = {
error: function (error) {
console.error(error.message);
}
};
// We use Babel to easily create named System.register modules
// See: https://github.com/Microsoft/TypeScript/issues/4801
// and https://github.com/ivogabe/gulp-typescript/issues/211
const babelOptions = {
moduleIds: true,
getModuleId: function (name) {
return 'ionic-angular/' + name;
},
plugins: ['transform-es2015-modules-systemjs'],
presets: [ES_2015]
};
/**
* Builds demos tests to dist/demos and watches for changes. Runs 'demos.bundle' or
* 'sass' on Ionic source changes and 'demos.build' for demos test changes.
*/
task('demos.watch', ['demos'], function () {
watchTask('demos.bundle');
watch('demos/src/**/*', function (file) {
start('demos.build');
});
});
function watchTask(task) {
watch([
'src/**/*.ts',
'!src/components/*/test/**/*',
'!src/util/test/*'
],
function (file) {
if (file.event !== 'unlink') {
start(task);
}
}
);
watch('src/**/*.scss', function () {
start('demos.sass');
});
start('demos.serve');
}

View File

@ -0,0 +1,242 @@
import { accessSync, F_OK, readFileSync, writeFileSync } from 'fs';
import { dirname, join } from 'path';
import * as glob from 'glob';
import { dest, src, start, task } from 'gulp';
import * as gulpif from 'gulp-if';
import * as watch from 'gulp-watch';
import * as rollup from 'rollup';
import * as nodeResolve from 'rollup-plugin-node-resolve';
import * as commonjs from 'rollup-plugin-commonjs';
import * as runSequence from 'run-sequence';
import { obj } from 'through2';
import * as VinylFile from 'vinyl';
import { argv } from 'yargs';
import { DEMOS_SRC_ROOT, DIST_DEMOS_COMPONENTS_ROOT, DIST_DEMOS_ROOT, DIST_NAME, DEMOS_NAME, ES5, ES_2015, LOCAL_SERVER_PORT, PROJECT_ROOT, SCRIPTS_ROOT, SRC_COMPONENTS_ROOT, SRC_ROOT } from '../constants';
import { createTempTsConfig, deleteFiles, runNgc } from '../util';
task('demos.prod', demosBuild);
function demosBuild(done: (err: any) => void) {
runSequence(
'demos.clean',
'demos.polyfill',
'demos.copySource',
'demos.compileTests',
'demos.copyExternalDependencies',
'demos.sass',
'demos.fonts',
'demos.bundleProd',
done);
}
task('demos.copySource', (done: Function) => {
const stream = src([`${SRC_ROOT}/**/*`, `!${SRC_ROOT}/components/*/test{,/**/*}`, `${DEMOS_SRC_ROOT}/**/*`])
.pipe(gulpif(/app.module.ts$/, createIndexHTML()))
.pipe(dest(DIST_DEMOS_ROOT));
stream.on('end', done);
function createIndexHTML() {
const indexTemplate = readFileSync(`${SCRIPTS_ROOT}/${DEMOS_NAME}/demos.template.prod.html`);
const indexTs = readFileSync(`${SCRIPTS_ROOT}/${DEMOS_NAME}/entry.ts`);
return obj(function (file, enc, next) {
this.push(new VinylFile({
base: file.base,
contents: new Buffer(indexTemplate),
path: join(dirname(file.path), 'index.html'),
}));
this.push(new VinylFile({
base: file.base,
contents: new Buffer(indexTs),
path: join(dirname(file.path), 'entry.ts'),
}));
next(null, file);
});
}
});
task('demos.compileTests', (done: Function) => {
let folderInfo = getFolderInfo();
buildDemoTests(folderInfo, done);
});
function buildDemoTests(folderInfo: any, done: Function) {
let includeGlob = ['./*/app.module.ts', './*/entry.ts'];
if (folderInfo.componentName && folderInfo.componentTest) {
includeGlob = [
`./${folderInfo.componentName}/app.module.ts`,
`./${folderInfo.componentName}/entry.ts`,
];
}
createTempTsConfig(includeGlob, ES5, ES_2015, `${DIST_DEMOS_ROOT}/tsconfig.json`);
runNgc(`${DIST_DEMOS_ROOT}/tsconfig.json`, (err) => {
if (err) {
done(err);
return;
}
// clean up any .ts files that remain
deleteFiles([`${DIST_DEMOS_ROOT}/**/*.ts`, `!${DIST_DEMOS_ROOT}/**/*.ngfactory.ts`, `!${DIST_DEMOS_ROOT}/**/*.d.ts`], done);
});
}
task('demos.bundleProd', (done) => {
let includeGlob = `${DIST_DEMOS_ROOT}/*/entry.js`;
let folderInfo = getFolderInfo();
if (folderInfo.componentName && folderInfo.componentTest) {
includeGlob = `${DIST_DEMOS_ROOT}/${folderInfo.componentName}/entry.js`;
}
glob(includeGlob, {}, function (er, files) {
var directories = files.map(function (file) {
return dirname(file);
});
let indexFileContents = directories.map(function (dir) {
let testName = dir.replace(`${DIST_DEMOS_ROOT}/`, '');
let fileName = dir.replace(`${PROJECT_ROOT}`, '');
return `<p><a href="${fileName}">${testName}</a></p>`;
}, []);
writeFileSync(`${DIST_DEMOS_ROOT}/index.html`,
'<!DOCTYPE html><html lang="en"><head></head><body style="width: 500px; margin: 100px auto">\n' +
indexFileContents.join('\n') +
'</center></body></html>'
);
createBundles(files).then(() => {
done();
}).catch(err => {
done(err);
});
});
});
function createBundles(files: string[]) {
let start;
if (!files) {
return Promise.reject(new Error('list of files is null'));
} else if (files.length === 0) {
return Promise.resolve();
} else {
const outputFileName = join(dirname(files[0]), 'app.bundle.js');
start = Date.now();
return bundle(files[0], outputFileName).then(() => {
const end = Date.now();
const seconds = (end - start) / 1000;
console.log(`Took ${seconds} seconds to process ${files[0]}`);
const remainingFiles = files.concat();
remainingFiles.shift();
return createBundles(remainingFiles);
}).catch(err => {
return Promise.reject(err);
});
}
}
function bundle(inputFile: string, outputFile: string): Promise<any> {
console.log(`Starting rollup on ${inputFile} ... writing to ${outputFile}`);
return rollup.rollup({
entry: inputFile,
plugins: [
commonjs(),
nodeResolve({
module: true,
jsnext: true,
main: true,
extensions: ['.js']
})
]
}).then(bundle => {
return bundle.write({
format: 'iife',
dest: outputFile,
});
});
}
task('demos.watchProd', ['demos.copyExternalDependencies', 'demos.sass', 'demos.fonts'], (done: Function) => {
const folderInfo = getFolderInfo();
let demoTestPath = DEMOS_SRC_ROOT;
if (folderInfo.componentName && folderInfo.componentTest) {
demoTestPath = join(DEMOS_SRC_ROOT, folderInfo.componentName, 'app.module.ts');
}
try {
accessSync(demoTestPath, F_OK);
} catch (e) {
done(new Error(`Could not find demos test: ${demoTestPath}`));
return;
}
if (demosComponentsExists()) {
// already generated the demos directory
demosWatch(folderInfo.componentName, folderInfo.componentTest);
} else {
// generate the demos directory
console.log('Generated demos builds first...');
demosBuild(() => {
demosWatch(folderInfo.componentName, folderInfo.componentTest);
});
}
});
function demosWatch(componentName: string, componentTest: string) {
// If any tests change within components then run demos.resources.
watch([
'demos/src/**/*'
],
function (file) {
console.log('start demos.resources - ' + JSON.stringify(file.history, null, 2));
start('demos.copyAndCompile');
});
// If any src files change except for tests then transpile only the source ionic files
watch([
'src/**/*.ts',
'!src/components/*/test/**/*',
'!src/util/test/*'
],
function (file) {
console.log('start demos.ngcSource - ' + JSON.stringify(file.history, null, 2));
start('demos.copyAndCompile');
});
// If any scss files change then recompile all sass
watch(['src/**/*.scss'], (file) => {
console.log('start sass - ' + JSON.stringify(file.history, null, 2));
start('demos.sass');
});
console.log(`http://localhost:${LOCAL_SERVER_PORT}/${DIST_NAME}/${DEMOS_NAME}/${componentName}`);
start('demos.serve');
}
function demosComponentsExists(): boolean {
try {
accessSync(DIST_DEMOS_COMPONENTS_ROOT, F_OK);
} catch (e) {
return false;
}
return true;
}
function getFolderInfo() {
let componentName: string = null;
let componentTest: string = null;
const folder: string = argv.folder || argv.f;
if (folder && folder.length) {
const folderSplit = folder.split('/');
componentName = folderSplit[0];
componentTest = (folderSplit.length > 1 ? folderSplit[1] : 'basic');
}
return {
componentName: componentName,
componentTest: componentTest
};
}

View File

@ -1,165 +1,55 @@
import { exec } from 'child_process';
import { dirname, join } from 'path';
import { dest, src, task } from 'gulp';
import * as connect from 'gulp-connect';
import * as del from 'del';
import * as runSequence from 'run-sequence';
import * as glob from 'glob';
import { task } from 'gulp';
import * as rollup from 'rollup';
import * as nodeResolve from 'rollup-plugin-node-resolve';
import * as commonjs from 'rollup-plugin-commonjs';
import { DEMOS_ROOT, DEMOS_SRC_ROOT} from '../constants';
import { compileSass, copyFonts, createTimestamp, deleteFiles, runNgc, setSassIonicVersion, writePolyfills } from '../util';
function doNpmInstall() {
return new Promise((resolve, reject) => {
// navigate to the demos directly
try {
process.chdir('./demos');
console.log('starting npm install ...');
exec('npm install', function(err, stdout, stderr) {
process.chdir('..');
console.log(stdout);
console.log(stderr);
if (err) {
reject(err);
} else {
resolve();
}
});
} catch (ex) {
reject(ex);
}
});
}
function generatePolyfills() {
return writePolyfills(join(DEMOS_ROOT, 'polyfills'));
}
function compileTests() {
console.log('Starting to compile tests defined via tsconfig ...');
return new Promise((resolve, reject) => {
runNgc(`${DEMOS_ROOT}/tsconfig.json`, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
function rollupTests() {
return new Promise((resolve, reject) => {
glob(`${DEMOS_SRC_ROOT}/**/main.js`, null, (err: Error, files: string[]) => {
if (err) {
reject(err);
} else {
recursiveRollupHelper(files).then(() => {
resolve();
}).catch(err => {
reject(err);
});
}
});
});
}
function recursiveRollupHelper(files: string[]) {
let start;
if (!files) {
return Promise.reject(new Error('list of files is null'));
} else if ( files.length === 0) {
return Promise.resolve();
} else {
const outputFileName = join(dirname(files[0]), 'main.bundle.js');
start = Date.now();
return bundle(files[0], outputFileName).then(() => {
const end = Date.now();
const seconds = (end - start) / 1000;
console.log(`Took ${seconds} seconds to process ${files[0]}`);
const remainingFiles = files.concat();
remainingFiles.shift();
return recursiveRollupHelper(remainingFiles);
}).catch(err => {
return Promise.reject(err);
});
}
}
function bundle(inputFile: string, outputFile: string): Promise<any> {
console.log(`Starting rollup on ${inputFile} ... writing to ${outputFile}`);
return rollup.rollup({
entry: inputFile,
plugins: [
commonjs(),
nodeResolve({
module: true,
jsnext: true,
main: true,
extensions: ['.js']
})
]
}).then(bundle => {
return bundle.write({
format: 'iife',
dest: outputFile,
});
});
}
function buildDemos(done: Function) {
doNpmInstall()
.then(() => {
return compileTests();
}).then(() => {
return rollupTests();
}).then(() => {
done();
}).catch(err => {
console.log('ERRROR: ', err.message);
done(err);
});
}
function cleanDemos(done: Function) {
deleteFiles([`${DEMOS_SRC_ROOT}/**/*.js`,
`${DEMOS_SRC_ROOT}/**/*.js.map`,
`${DEMOS_SRC_ROOT}/**/*.d.ts`,
`${DEMOS_SRC_ROOT}/**/*.ngfactory.ts`,
`${DEMOS_SRC_ROOT}/**/*.metadata.json`,
`${DEMOS_ROOT}/css`,
`${DEMOS_ROOT}/fonts`,
`${DEMOS_ROOT}/polyfills`,
`!${DEMOS_SRC_ROOT}/scrollbar-fix.css`,
`!${DEMOS_SRC_ROOT}/scrollbar-fix.js`,
], done);
}
task('demos.build', ['demos.sass', 'demos.fonts', 'demos.polyfills'], (done: Function) => {
buildDemos(done);
});
import { DEMOS_NAME, DIST_DEMOS_ROOT, LOCAL_SERVER_PORT, SCRIPTS_ROOT } from '../constants';
import { compileSass, copyFonts, createTimestamp, setSassIonicVersion, writePolyfills } from '../util';
task('demos.clean', (done: Function) => {
cleanDemos(done);
del([`${DIST_DEMOS_ROOT}/**`]).then(() => {
done();
}).catch(err => {
done(err);
});
});
task('demos.polyfill', (done: Function) => {
writePolyfills(`${DIST_DEMOS_ROOT}/polyfills`).then(() => {
done();
}).catch(err => {
done(err);
});
});
task('demos.copyAndCompile', (done: (err: any) => void) => {
runSequence(
'demos.copySource',
'demos.compileTests',
'demos.bundle',
done);
});
task('demos.copyExternalDependencies', () => {
src([`${SCRIPTS_ROOT}/${DEMOS_NAME}/*.css`]).pipe(dest(`${DIST_DEMOS_ROOT}/css`));
});
task('demos.sass', () => {
// ensure there is a version.scss file
setSassIonicVersion(`E2E-${createTimestamp()}`);
return compileSass(`${DEMOS_ROOT}/css`);
return compileSass(`${DIST_DEMOS_ROOT}/css`);
});
task('demos.fonts', () => {
return copyFonts(`${DEMOS_ROOT}/fonts`);
return copyFonts(`${DIST_DEMOS_ROOT}/fonts`);
});
task('demos.polyfills', (done: Function) => {
generatePolyfills().then(() => {
done();
}).catch(err => {
done(err);
task('demos.serve', function() {
connect.server({
root: './',
port: LOCAL_SERVER_PORT,
livereload: {
port: 35700
}
});
});
});

View File

@ -9,7 +9,7 @@ import * as mkdirp from 'mkdirp';
import { valid }from 'semver';
import { argv } from 'yargs';
import { DEMOS_ROOT } from '../constants';
import { DIST_DEMOS_ROOT } from '../constants';
task('docs', ['docs.dgeni', 'docs.demos', 'docs.sassVariables']);
@ -30,7 +30,7 @@ task('docs.dgeni', () => {
}
});
task('docs.demos', ['demos.build'], (done: Function) => {
task('docs.demos', ['demos.prod'], (done: Function) => {
const config = require('../../config.json');
const outputDir = join(config.docsDest, 'demos');
let promises = [];
@ -47,7 +47,7 @@ task('docs.demos', ['demos.build'], (done: Function) => {
function copyDemoCss(outputDir: string) {
return new Promise((resolve, reject) => {
const stream = src(`${DEMOS_ROOT}/css/*`).pipe(dest(outputDir));
const stream = src(`${DIST_DEMOS_ROOT}/css/*`).pipe(dest(outputDir));
stream.on('end', () => {
resolve();
});
@ -56,7 +56,7 @@ function copyDemoCss(outputDir: string) {
function copyDemoFonts(outputDir: string) {
return new Promise((resolve, reject) => {
const stream = src(`${DEMOS_ROOT}/fonts/*`).pipe(dest(outputDir));
const stream = src(`${DIST_DEMOS_ROOT}/fonts/*`).pipe(dest(outputDir));
stream.on('end', () => {
resolve();
});
@ -65,7 +65,7 @@ function copyDemoFonts(outputDir: string) {
function copyDemoPolyfills(outputDir: string) {
return new Promise((resolve, reject) => {
const stream = src(`${DEMOS_ROOT}/polyfills/*`).pipe(dest(outputDir));
const stream = src(`${DIST_DEMOS_ROOT}/polyfills/*`).pipe(dest(outputDir));
stream.on('end', () => {
resolve();
});
@ -75,8 +75,7 @@ function copyDemoPolyfills(outputDir: string) {
function copyDemoContent(outputDir: string) {
return new Promise((resolve, reject) => {
const stream = src([
`${DEMOS_ROOT}/src/**/*`,
`${DEMOS_ROOT}/src/scrollbar-fix.*`
`${DIST_DEMOS_ROOT}/**/*`
]).pipe(dest(outputDir));
stream.on('end', () => {
resolve();