mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 11:41:20 +08:00
chore(): begin adding ionic components to mono-repo.
This commit is contained in:
98
packages/ionic-angular/scripts/gulp/tasks/build.ts
Normal file
98
packages/ionic-angular/scripts/gulp/tasks/build.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { task } from 'gulp';
|
||||
import { join } from 'path';
|
||||
import { DIST_BUILD_ROOT, DIST_BUILD_ES2015_ROOT, DIST_BUILD_UMD_ROOT, ES5, ES_2015, PROJECT_ROOT, UMD_MODULE } from '../constants';
|
||||
import { copySourceToDest, createTempTsConfig, deleteFiles, runNgc, runTsc } from '../util';
|
||||
|
||||
|
||||
export function buildIonicAngularUmd(excludeSpec: boolean, stripDebug: boolean, done: Function) {
|
||||
const stream = copySourceToDest(DIST_BUILD_UMD_ROOT, excludeSpec, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES5, UMD_MODULE, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'));
|
||||
runNgc(join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// clean up any .ts files that remain as well as ngc metadata
|
||||
deleteFiles([`${DIST_BUILD_UMD_ROOT}/**/*.ts`,
|
||||
`${DIST_BUILD_UMD_ROOT}/node_modules`,
|
||||
`${DIST_BUILD_UMD_ROOT}/tsconfig.json`,
|
||||
`!${DIST_BUILD_UMD_ROOT}/**/*.d.ts`], done);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function buildIonicAngularUmdTsc(excludeSpec: boolean, stripDebug: boolean, done: Function) {
|
||||
const stream = copySourceToDest(DIST_BUILD_UMD_ROOT, excludeSpec, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES5, UMD_MODULE, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'));
|
||||
runTsc(join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// clean up any .ts files that remain as well as ngc metadata
|
||||
deleteFiles([`${DIST_BUILD_UMD_ROOT}/**/*.ts`,
|
||||
`${DIST_BUILD_UMD_ROOT}/node_modules`,
|
||||
`${DIST_BUILD_UMD_ROOT}/tsconfig.json`,
|
||||
`!${DIST_BUILD_UMD_ROOT}/**/*.d.ts`], done);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function buildIonicAngularEsm(stripDebug: boolean, done: Function) {
|
||||
const stream = copySourceToDest(DIST_BUILD_ROOT, true, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES5, ES_2015, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_ROOT, 'tsconfig.json'));
|
||||
runNgc(join(DIST_BUILD_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
}
|
||||
// clean up any .ts files that remain as well as ngc metadata
|
||||
deleteFiles([`${DIST_BUILD_ROOT}/**/*.ts`,
|
||||
`${DIST_BUILD_ROOT}/node_modules`,
|
||||
`${DIST_BUILD_ROOT}/tsconfig.json`,
|
||||
`!${DIST_BUILD_ROOT}/**/*.d.ts`], done);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function buildIonicPureEs6(stripDebug: boolean, done: Function) {
|
||||
const stream = copySourceToDest(DIST_BUILD_ES2015_ROOT, true, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES_2015, ES_2015, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_ES2015_ROOT, 'tsconfig.json'));
|
||||
runNgc(join(DIST_BUILD_ES2015_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
}
|
||||
// clean up any .ts files that remain as well as ngc metadata
|
||||
deleteFiles([`${DIST_BUILD_ES2015_ROOT}/**/*.ts`,
|
||||
`${DIST_BUILD_ES2015_ROOT}/node_modules`,
|
||||
`${DIST_BUILD_ES2015_ROOT}/tsconfig.json`,
|
||||
`!${DIST_BUILD_ES2015_ROOT}/**/*.d.ts`], done);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* this task builds out the necessary stuff for karma */
|
||||
task('compile.karma', (done: Function) => {
|
||||
buildIonicAngularUmdTsc(false, false, done);
|
||||
});
|
||||
|
||||
/* this task builds out the ionic-angular (commonjs and esm) directories for release */
|
||||
task('compile.release', (done: Function) => {
|
||||
buildIonicAngularEsm(true, () => {
|
||||
buildIonicAngularUmd(true, true, () => {
|
||||
buildIonicPureEs6(true, done);
|
||||
});
|
||||
});
|
||||
});
|
18
packages/ionic-angular/scripts/gulp/tasks/clean.ts
Normal file
18
packages/ionic-angular/scripts/gulp/tasks/clean.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import * as del from 'del';
|
||||
import { task } from 'gulp';
|
||||
|
||||
task('clean', (done: Function) => {
|
||||
del(['dist/**']).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
task('clean.src', (done: Function) => {
|
||||
del(['src/**/*.js', 'src/**/*.d.ts']).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
56
packages/ionic-angular/scripts/gulp/tasks/core.ts
Normal file
56
packages/ionic-angular/scripts/gulp/tasks/core.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { PROJECT_ROOT } from '../constants';
|
||||
import { task } from 'gulp';
|
||||
import { accessSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
|
||||
task('core', (done) => {
|
||||
buildAngularBinding(false, done);
|
||||
});
|
||||
|
||||
task('core.watch', (done) => {
|
||||
buildAngularBinding(true, done);
|
||||
});
|
||||
|
||||
|
||||
function buildAngularBinding(isDevAndWatch: boolean, done: Function) {
|
||||
let hasRunDone = false;
|
||||
const cwd = join(PROJECT_ROOT, '../ionic-core');
|
||||
const args = [
|
||||
'run',
|
||||
'build.angular'
|
||||
];
|
||||
|
||||
if (isDevAndWatch) {
|
||||
args.push('--', 'dev', 'watch');
|
||||
}
|
||||
|
||||
try {
|
||||
accessSync(cwd);
|
||||
} catch (e) {
|
||||
console.log('core directory not found:', cwd);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const spawn = require('child_process').spawn;
|
||||
const ls = spawn('npm', args, { cwd: cwd });
|
||||
|
||||
ls.stdout.on('data', (data) => {
|
||||
console.log(data.toString().trim());
|
||||
if (!hasRunDone && data.toString().trim().indexOf('compile, done') > -1) {
|
||||
hasRunDone = true;
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
ls.stderr.on('data', (data) => {
|
||||
console.log(data.toString().trim());
|
||||
});
|
||||
|
||||
ls.on('close', (code) => {
|
||||
if (!hasRunDone) {
|
||||
hasRunDone = true;
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
19
packages/ionic-angular/scripts/gulp/tasks/default.ts
Normal file
19
packages/ionic-angular/scripts/gulp/tasks/default.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import * as gulp from 'gulp';
|
||||
import * as runSequence from 'run-sequence';
|
||||
|
||||
gulp.task('default', help);
|
||||
|
||||
gulp.task('help', help);
|
||||
|
||||
function help() {
|
||||
const taskList = Object.keys((gulp as any).tasks)
|
||||
.filter(taskName => taskName !== 'default' && taskName !== 'help')
|
||||
.sort()
|
||||
.map(taskName => taskName = ' ' + taskName);
|
||||
|
||||
console.log(taskList.join('\n'));
|
||||
}
|
||||
|
||||
gulp.task('validate', (done: (err: any) => void) => {
|
||||
runSequence('clean', ['lint', 'test'], done);
|
||||
});
|
46
packages/ionic-angular/scripts/gulp/tasks/demos.dev.ts
Normal file
46
packages/ionic-angular/scripts/gulp/tasks/demos.dev.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { join } from 'path';
|
||||
|
||||
import { task } from 'gulp';
|
||||
|
||||
import { DEMOS_ROOT, DIST_DEMOS_ROOT, ES_2015, PROJECT_ROOT } from '../constants';
|
||||
import { createTempTsConfig, getFolderInfo, runAppScriptsServe } from '../util';
|
||||
|
||||
task('demos.watch', ['demos.prepare'], (done: Function) => {
|
||||
const folderInfo = getFolderInfo();
|
||||
if (!folderInfo || !folderInfo.componentName ) {
|
||||
done(new Error(`Usage: gulp e2e.watch --folder modal`));
|
||||
}
|
||||
|
||||
serveDemo(folderInfo.componentName).then(() => {
|
||||
done();
|
||||
}).catch((err: Error) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
function serveDemo(folderName: any) {
|
||||
const testOrDemoName = folderName;
|
||||
const ionicAngularDir = join(PROJECT_ROOT, 'src');
|
||||
const coreCompilerFilePath = join(PROJECT_ROOT, 'dist', 'ionic-angular', 'compiler');
|
||||
const coreDir = join(PROJECT_ROOT, 'dist', 'ionic-angular');
|
||||
const srcTestRoot = join(DEMOS_ROOT, 'src', folderName);
|
||||
const distDemoRoot = join(DIST_DEMOS_ROOT, folderName);
|
||||
const includeGlob = [ join(ionicAngularDir, '**', '*.ts'),
|
||||
join(srcTestRoot, '**', '*.ts')];
|
||||
|
||||
|
||||
const pathToWriteFile = join(distDemoRoot, 'tsconfig.json');
|
||||
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||
|
||||
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||
|
||||
const sassConfigPath = join('scripts', 'demos', 'sass.config.js');
|
||||
const copyConfigPath = join('scripts', 'demos', 'copy.config.js');
|
||||
const watchConfigPath = join('scripts', 'demos', 'watch.config.js');
|
||||
|
||||
const appEntryPoint = join(srcTestRoot, 'app', 'main.ts');
|
||||
const appNgModulePath = join(srcTestRoot, 'app', 'app.module.ts');
|
||||
const distDir = join(distDemoRoot, 'www');
|
||||
|
||||
return runAppScriptsServe(testOrDemoName, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, coreCompilerFilePath, coreDir, sassConfigPath, copyConfigPath, watchConfigPath);
|
||||
}
|
229
packages/ionic-angular/scripts/gulp/tasks/demos.prod.ts
Normal file
229
packages/ionic-angular/scripts/gulp/tasks/demos.prod.ts
Normal file
@ -0,0 +1,229 @@
|
||||
import { dirname, join, relative } from 'path';
|
||||
|
||||
import * as glob from 'glob';
|
||||
import { task } from 'gulp';
|
||||
import * as del from 'del';
|
||||
import * as runSequence from 'run-sequence';
|
||||
import * as s3 from 's3';
|
||||
import { argv } from 'yargs';
|
||||
|
||||
|
||||
import { DEMOS_SRC_ROOT, ES_2015, PROJECT_ROOT } from '../constants';
|
||||
import { createTempTsConfig, getFolderInfo, runAppScriptsBuild, writePolyfills } from '../util';
|
||||
|
||||
import * as pAll from 'p-all';
|
||||
|
||||
import * as dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
task('demos.prepare', (done: Function) => {
|
||||
runSequence('demos.clean', 'demos.polyfill', 'demos.sass', (err: any) => done(err));
|
||||
});
|
||||
|
||||
task('demos.prod', ['demos.prepare'], (done: Function) => {
|
||||
|
||||
// okay, first find out all of the demos tests to run by finding all of the 'main.ts' files
|
||||
filterDemosEntryPoints().then((filePaths: string[]) => {
|
||||
return buildDemos(filePaths);
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch((err: Error) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
function filterDemosEntryPoints() {
|
||||
return getDemosEntryPoints().then((entryPoints: string[]) => {
|
||||
const folderInfo = getFolderInfo();
|
||||
if (folderInfo && folderInfo.componentName) {
|
||||
const filtered = entryPoints.filter(entryPoint => {
|
||||
return entryPoint.indexOf(folderInfo.componentName) >= 0;
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
return entryPoints;
|
||||
});
|
||||
}
|
||||
|
||||
function getDemosEntryPoints() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const mainGlob = join(DEMOS_SRC_ROOT, '**', 'main.ts');
|
||||
glob(mainGlob, (err: Error, matches: string[]) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(matches);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function buildDemos(filePaths: string[]) {
|
||||
var batches = chunkArrayInGroups(filePaths, argv.batches || 1);
|
||||
var batch = argv.batch || 0;
|
||||
if(batch >= batches.length) {
|
||||
throw new Error(`Batch number higher than total number of batches.`);
|
||||
}
|
||||
|
||||
console.log(`Compiling ${batches[batch].length} of ${filePaths.length} Demos ...`);
|
||||
|
||||
const functions = batches[batch].map(filePath => () => {
|
||||
return buildDemo(filePath);
|
||||
});
|
||||
let concurrentNumber = 2;
|
||||
if (argv.concurrency) {
|
||||
concurrentNumber = argv.concurrency;
|
||||
}
|
||||
return pAll(functions, {concurrency: concurrentNumber});
|
||||
}
|
||||
|
||||
function buildDemo(filePath: string) {
|
||||
const start = Date.now();
|
||||
const ionicAngularDir = join(process.cwd(), 'src');
|
||||
|
||||
const componentDir = dirname(dirname(filePath));
|
||||
const relativePathFromComponents = relative(dirname(DEMOS_SRC_ROOT), componentDir);
|
||||
|
||||
const distTestRoot = join(process.cwd(), 'dist', 'demos', relativePathFromComponents);
|
||||
const coreCompilerFilePath = join(PROJECT_ROOT, '..', 'ionic-core', 'dist', 'compiler');
|
||||
const coreDir = join(PROJECT_ROOT, '..', 'ionic-core', 'dist', 'compiled-ionic-angular');
|
||||
|
||||
const includeGlob = [ join(ionicAngularDir, '**', '*.ts'), join(componentDir, '**', '*.ts')];
|
||||
const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
|
||||
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||
|
||||
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||
|
||||
const sassConfigPath = join('scripts', 'demos', 'sass.config.js');
|
||||
const copyConfigPath = join('scripts', 'demos', 'copy.config.js');
|
||||
|
||||
const appEntryPoint = filePath;
|
||||
const appNgModulePath = join(dirname(filePath), 'app.module.ts');
|
||||
const distDir = join(distTestRoot, 'www');
|
||||
|
||||
return runAppScriptsBuild(
|
||||
appEntryPoint,
|
||||
appNgModulePath,
|
||||
ionicAngularDir,
|
||||
coreCompilerFilePath,
|
||||
coreDir,
|
||||
distDir,
|
||||
pathToWriteFile,
|
||||
ionicAngularDir,
|
||||
sassConfigPath,
|
||||
copyConfigPath,
|
||||
argv.dev
|
||||
).then(() => {
|
||||
const end = Date.now();
|
||||
console.log(`${filePath} took a total of ${(end - start) / 1000} seconds to build`);
|
||||
uploadToS3(pathToWriteFile);
|
||||
});
|
||||
}
|
||||
|
||||
function chunkArrayInGroups(arr, size) {
|
||||
var result = [];
|
||||
for(var i = 0; i < arr.length; i++) {
|
||||
if (!Array.isArray(result[i % size])) {
|
||||
result[i % size] = [];
|
||||
}
|
||||
result[i % size].push(arr[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function uploadToS3(path) {
|
||||
// fail silently if envars not present
|
||||
if (!process.env.AWS_KEY || !process.env.AWS_SECRET) {
|
||||
return new Promise((resolve) => {resolve();});
|
||||
}
|
||||
|
||||
let client = s3.createClient({
|
||||
s3Options: {
|
||||
accessKeyId: process.env.AWS_KEY,
|
||||
secretAccessKey: process.env.AWS_SECRET
|
||||
},
|
||||
});
|
||||
|
||||
// get demo name from path
|
||||
let demo = path.split('/')[path.split('/').length - 2];
|
||||
|
||||
let params = {
|
||||
localDir: path.replace('tsconfig.json',''),
|
||||
deleteRemoved: true,
|
||||
s3Params: {
|
||||
Bucket: "ionic-demos",
|
||||
Prefix: demo,
|
||||
},
|
||||
};
|
||||
|
||||
var uploader = client.uploadDir(params);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uploader.on('error', function(err) {
|
||||
console.error("s3 Upload Error:", err.stack);
|
||||
reject();
|
||||
});
|
||||
uploader.on('end', function() {
|
||||
console.log(demo, " demo uploaded to s3");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
task('demos.download', (done: Function) => {
|
||||
if (!process.env.AWS_KEY || !process.env.AWS_SECRET) {
|
||||
return new Promise((resolve) => {resolve();});
|
||||
}
|
||||
|
||||
let client = s3.createClient({
|
||||
s3Options: {
|
||||
accessKeyId: process.env.AWS_KEY,
|
||||
secretAccessKey: process.env.AWS_SECRET
|
||||
},
|
||||
});
|
||||
|
||||
let params = {
|
||||
localDir: join(process.cwd(), 'dist', 'demos', 'src'),
|
||||
s3Params: {
|
||||
Bucket: "ionic-demos",
|
||||
},
|
||||
};
|
||||
|
||||
let uploader = client.downloadDir(params);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uploader.on('error', function(err) {
|
||||
console.error("s3 Download Error:", err.stack);
|
||||
reject();
|
||||
});
|
||||
uploader.on('end', function() {
|
||||
console.log("Demos downloaded from s3");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
task('demos.clean', (done: Function) => {
|
||||
// this is a super hack, but it works for now
|
||||
if (argv.skipClean) {
|
||||
return done();
|
||||
}
|
||||
|
||||
del(['dist/demos/**']).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
task('demos.polyfill', (done: Function) => {
|
||||
if (argv.skipPolyfill) {
|
||||
return done();
|
||||
}
|
||||
|
||||
writePolyfills('dist/demos/polyfills').then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
55
packages/ionic-angular/scripts/gulp/tasks/demos.ts
Normal file
55
packages/ionic-angular/scripts/gulp/tasks/demos.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { dest, src, task } from 'gulp';
|
||||
import * as connect from 'gulp-connect';
|
||||
import * as del from 'del';
|
||||
import * as runSequence from 'run-sequence';
|
||||
|
||||
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) => {
|
||||
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(`${DIST_DEMOS_ROOT}/css`);
|
||||
});
|
||||
|
||||
task('demos.fonts', () => {
|
||||
return copyFonts(`${DIST_DEMOS_ROOT}/fonts`);
|
||||
});
|
||||
|
||||
task('demos.serve', function() {
|
||||
connect.server({
|
||||
root: './',
|
||||
port: LOCAL_SERVER_PORT,
|
||||
livereload: {
|
||||
port: 35700
|
||||
}
|
||||
});
|
||||
});
|
153
packages/ionic-angular/scripts/gulp/tasks/docs.ts
Normal file
153
packages/ionic-angular/scripts/gulp/tasks/docs.ts
Normal file
@ -0,0 +1,153 @@
|
||||
import { createReadStream, writeFileSync } from 'fs';
|
||||
import { join, relative } from 'path';
|
||||
|
||||
import * as Dgeni from 'dgeni';
|
||||
import { split, map } from 'event-stream';
|
||||
import { src, dest, task } from 'gulp';
|
||||
import { AllHtmlEntities } from 'html-entities';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import { valid }from 'semver';
|
||||
import { argv } from 'yargs';
|
||||
|
||||
import { DIST_DEMOS_ROOT } from '../constants';
|
||||
import { SITE_ROOT } from '../constants';
|
||||
import { PROJECT_ROOT } from '../constants';
|
||||
|
||||
task('docs', ['docs.dgeni', 'docs.demos', 'docs.sassVariables']);
|
||||
|
||||
task('docs.dgeni', () => {
|
||||
const docVersion = argv['doc-version'] || 'nightly';
|
||||
const initialVersionBuild = argv['initial-build'] || false;
|
||||
if (docVersion !== 'nightly' && ! valid(docVersion)) {
|
||||
console.log('Usage: gulp docs --doc-version=(nightly|versionName)\nversionName must be a valid semver version.');
|
||||
return process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
const ionicPackage = require('../../docs/dgeni-config')(docVersion, initialVersionBuild);
|
||||
const dgeni = new Dgeni([ionicPackage]);
|
||||
return dgeni.generate();
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
});
|
||||
|
||||
task('docs.demos', (done: Function) => {
|
||||
// Copy demos already built from gulp demos.prod task to ionic-site
|
||||
const config = require('../../config.json');
|
||||
const outputDir = join(config.docsDest, 'demos');
|
||||
let promises = [];
|
||||
promises.push(copyDemoCss(join(outputDir, 'css')));
|
||||
promises.push(copyDemoFonts(join(outputDir, 'fonts')));
|
||||
promises.push(copyDemoPolyfills(join(outputDir, 'polyfills')));
|
||||
promises.push(copyDemoContent(join(outputDir, 'src')));
|
||||
Promise.all(promises).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
function copyDemoCss(outputDir: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = src(`${DIST_DEMOS_ROOT}/css/*`).pipe(dest(outputDir));
|
||||
stream.on('end', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyDemoFonts(outputDir: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = src(`${DIST_DEMOS_ROOT}/fonts/*`).pipe(dest(outputDir));
|
||||
stream.on('end', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyDemoPolyfills(outputDir: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = src(`${DIST_DEMOS_ROOT}/polyfills/*`).pipe(dest(outputDir));
|
||||
stream.on('end', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyDemoContent(outputDir: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = src([
|
||||
`${DIST_DEMOS_ROOT}/src/**/*`
|
||||
]).pipe(dest(outputDir));
|
||||
stream.on('end', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
task('docs.sassVariables', () => {
|
||||
let variables = [];
|
||||
const outputFile = 'tmp/sass.json';
|
||||
|
||||
function addVariable(variableName, defaultValue, file) {
|
||||
const entities = new AllHtmlEntities();
|
||||
defaultValue = entities.encode(defaultValue);
|
||||
defaultValue = defaultValue.replace('!default;', '');
|
||||
|
||||
variables.push({
|
||||
name: variableName,
|
||||
defaultValue: defaultValue.trim(),
|
||||
file: relative('./', file.path)
|
||||
});
|
||||
}
|
||||
|
||||
return src('./src/**/*.scss')
|
||||
.pipe(map((file, callback) => {
|
||||
let variableLine, variableName, defaultValue, multiline;
|
||||
createReadStream(file.path, { flags: 'r'})
|
||||
.pipe(split())
|
||||
.pipe(map((line, callback) => {
|
||||
if (line.charAt(0) === '$') {
|
||||
variableLine = line.split(/:(.+)/);
|
||||
variableName = variableLine[0];
|
||||
defaultValue = variableLine[1];
|
||||
|
||||
// If there is a semicolon then it isn't a multiline value
|
||||
multiline = line.indexOf(';') > -1 ? false : true;
|
||||
if (!multiline && line.indexOf('!default') > -1) {
|
||||
addVariable(variableName, defaultValue, file);
|
||||
}
|
||||
} else if (multiline === true) {
|
||||
defaultValue += '\n' + line;
|
||||
|
||||
// If the line has a semicolon then we've found the end of the value
|
||||
if (line.indexOf(';') > -1 && line.indexOf('!default') > -1) {
|
||||
addVariable(variableName, defaultValue, file);
|
||||
multiline = false;
|
||||
}
|
||||
}
|
||||
callback();
|
||||
}));
|
||||
callback();
|
||||
}).on('end', () => {
|
||||
const config = require('../../config.json');
|
||||
console.log(`Writing to file at /ionic-team/ionic/${outputFile}`);
|
||||
console.log(`Place this file in /ionic-team/ionic-site/${config.v2DocsDir}/theming/overriding-ionic-variables in order to update the docs`);
|
||||
mkdirp.sync('tmp');
|
||||
writeFileSync(outputFile, JSON.stringify(variables));
|
||||
}));
|
||||
});
|
||||
|
||||
task('docs.homepageVersionUpdate', () => {
|
||||
// This assumes you're currently releasing
|
||||
const sourcePackageJSON = require(`${PROJECT_ROOT}/package.json`);
|
||||
let now = new Date();
|
||||
|
||||
const frameworkInfo = JSON.stringify({
|
||||
version: sourcePackageJSON.version,
|
||||
date: now.toISOString().split('T')[0]
|
||||
}, null, 2);
|
||||
|
||||
writeFileSync(`${SITE_ROOT}/server/data/framework-info.json`, frameworkInfo);
|
||||
});
|
53
packages/ionic-angular/scripts/gulp/tasks/e2e.dev.ts
Normal file
53
packages/ionic-angular/scripts/gulp/tasks/e2e.dev.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { dirname, join } from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
import { task } from 'gulp';
|
||||
|
||||
import { ES_2015, PROJECT_ROOT } from '../constants';
|
||||
import { createTempTsConfig, getFolderInfo, runAppScriptsServe } from '../util';
|
||||
|
||||
task('e2e.watch', ['e2e.prepare', 'core.watch'], (done: Function) => {
|
||||
const folderInfo = getFolderInfo();
|
||||
if (!folderInfo || !folderInfo.componentName || !folderInfo.componentTest) {
|
||||
done(new Error(`Usage: gulp e2e.watch --folder nav/basic`));
|
||||
return;
|
||||
}
|
||||
|
||||
serveTest(folderInfo).then(() => {
|
||||
done();
|
||||
}).catch((err: Error) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
function serveTest(folderInfo: any) {
|
||||
const testOrDemoName = join(folderInfo.componentName, folderInfo.componentTest);
|
||||
const ionicAngularDir = join(PROJECT_ROOT, 'src');
|
||||
const coreCompilerFilePath = join(PROJECT_ROOT, '..', 'ionic-core', 'dist', 'compiler');
|
||||
const coreDir = join(PROJECT_ROOT, '..', 'ionic-core', 'dist', 'compiled-ionic-angular');
|
||||
const srcTestRoot = join(PROJECT_ROOT, 'src', 'components', folderInfo.componentName, 'test', folderInfo.componentTest);
|
||||
const distTestRoot = join(PROJECT_ROOT, 'dist', 'e2e', 'components', folderInfo.componentName, 'test', folderInfo.componentTest);
|
||||
const includeGlob = [ join(ionicAngularDir, '**', '*.ts')];
|
||||
const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
|
||||
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||
|
||||
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||
|
||||
const sassConfigPath = join('scripts', 'e2e', 'sass.config.js');
|
||||
const copyConfigPath = join('scripts', 'e2e', 'copy.config.js');
|
||||
|
||||
let appEntryPoint = join(srcTestRoot, 'app', 'main.ts');
|
||||
try {
|
||||
// check if the entry point exists, otherwise fall back to the legacy entry point without 'app' folder
|
||||
readFileSync(appEntryPoint);
|
||||
} catch (ex) {
|
||||
// the file doesn't exist, so use the legacy entry point
|
||||
appEntryPoint = join(srcTestRoot, 'main.ts');
|
||||
}
|
||||
|
||||
// this assume that app.module.ts and main.ts are peers, which they should be no matter what
|
||||
const appNgModulePath = join(dirname(appEntryPoint), 'app.module.ts');
|
||||
const distDir = join(distTestRoot, 'www');
|
||||
|
||||
return runAppScriptsServe(testOrDemoName, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, coreCompilerFilePath, coreDir, sassConfigPath, copyConfigPath, null);
|
||||
}
|
263
packages/ionic-angular/scripts/gulp/tasks/e2e.prod.ts
Normal file
263
packages/ionic-angular/scripts/gulp/tasks/e2e.prod.ts
Normal file
@ -0,0 +1,263 @@
|
||||
import { spawn } from 'child_process';
|
||||
import { accessSync, readFileSync, writeFileSync } from 'fs';
|
||||
import { dirname, join, relative } from 'path';
|
||||
|
||||
import * as glob from 'glob';
|
||||
import { task } from 'gulp';
|
||||
import * as del from 'del';
|
||||
import { template } from 'lodash';
|
||||
import * as runSequence from 'run-sequence';
|
||||
import { argv } from 'yargs';
|
||||
|
||||
|
||||
import { DIST_E2E_COMPONENTS_ROOT, ES_2015, PROJECT_ROOT, SRC_ROOT, SRC_COMPONENTS_ROOT, SCRIPTS_ROOT } from '../constants';
|
||||
import { createTempTsConfig, createTimestamp, getFolderInfo, readFileAsync, runAppScriptsBuild, writeFileAsync, writePolyfills } from '../util';
|
||||
|
||||
import * as pAll from 'p-all';
|
||||
|
||||
task('e2e.prepare', (done: Function) => {
|
||||
runSequence('e2e.clean', 'e2e.polyfill', 'e2e.prepareSass', (err: any) => done(err));
|
||||
});
|
||||
|
||||
task('e2e.prepareSass', (done: Function) => {
|
||||
const version = `E2E-${createTimestamp()}`;
|
||||
writeFileSync(join(SRC_ROOT, 'themes', 'version.scss'), `$ionic-version: "${version}";`);
|
||||
done();
|
||||
});
|
||||
|
||||
task('e2e.prod', ['e2e.prepare', 'core'], (done: Function) => {
|
||||
// okay, first find out all of the e2e tests to run by finding all of the 'main.ts' files
|
||||
filterE2eTestfiles().then((filePaths: string[]) => {
|
||||
if (filePaths && filePaths.length > 0) {
|
||||
console.log(`Compiling ${filePaths.length} E2E tests ...`);
|
||||
return buildTests(filePaths);
|
||||
}
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch((err: Error) => {
|
||||
done(err);
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
|
||||
function e2eComponentExists(folderInfo: any): boolean {
|
||||
let componentPath = join(SRC_COMPONENTS_ROOT, folderInfo.componentName, 'test', folderInfo.componentTest, 'app');
|
||||
|
||||
try {
|
||||
accessSync(componentPath);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function filterE2eTestfiles() {
|
||||
return getE2eTestFiles().then((filePaths: string[]) => {
|
||||
const entryPoints = filePaths.map(filePath => {
|
||||
const directoryName = dirname(filePath);
|
||||
return join(directoryName, 'app', 'main.ts');
|
||||
});
|
||||
return entryPoints;
|
||||
}).then((entryPoints: string[]) => {
|
||||
const folderInfo = getFolderInfo();
|
||||
if (folderInfo && folderInfo.componentName && folderInfo.componentTest) {
|
||||
if (!e2eComponentExists(folderInfo)) {
|
||||
console.log('Cannot find E2E test ', join(folderInfo.componentName, 'test', folderInfo.componentTest), '. Make sure that the test exists and you are passing the correct folder.');
|
||||
return [];
|
||||
}
|
||||
const filtered = entryPoints.filter(entryPoint => {
|
||||
return entryPoint.indexOf(join(folderInfo.componentName, 'test', folderInfo.componentTest)) >= 0;
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
return entryPoints;
|
||||
});
|
||||
}
|
||||
|
||||
function getE2eTestFiles() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const mainGlob = join(SRC_COMPONENTS_ROOT, '*', 'test', '*', 'e2e.ts');
|
||||
glob(mainGlob, (err: Error, matches: string[]) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(matches);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function buildTests(filePaths: string[]) {
|
||||
const functions = filePaths.map(filePath => () => {
|
||||
return buildTest(filePath);
|
||||
});
|
||||
|
||||
// Run 2 tests at a time unless the `concurrency` arg is passed
|
||||
let concurrentNumber = 2;
|
||||
if (argv.concurrency) {
|
||||
concurrentNumber = argv.concurrency;
|
||||
}
|
||||
return pAll(functions, {concurrency: concurrentNumber}).then(() => {
|
||||
// copy over all of the protractor tests to the correct location now
|
||||
return copyProtractorTestContent(filePaths);
|
||||
});
|
||||
}
|
||||
|
||||
function buildTest(filePath: string) {
|
||||
const start = Date.now();
|
||||
const ionicAngularDir = join(process.cwd(), 'src');
|
||||
|
||||
let appEntryPoint = filePath;
|
||||
let srcTestRoot = dirname(dirname(appEntryPoint));
|
||||
try {
|
||||
// check if the entry point exists, otherwise fall back to the legacy entry point without 'app' folder
|
||||
readFileSync(appEntryPoint);
|
||||
} catch (ex) {
|
||||
// the file doesn't exist, so use the legacy entry point
|
||||
appEntryPoint = join(dirname(dirname(appEntryPoint)), 'main.ts');
|
||||
srcTestRoot = dirname(appEntryPoint);
|
||||
}
|
||||
|
||||
const relativePathFromComponents = relative(dirname(SRC_COMPONENTS_ROOT), srcTestRoot);
|
||||
const distTestRoot = join(process.cwd(), 'dist', 'e2e', relativePathFromComponents);
|
||||
const coreCompilerFilePath = join(PROJECT_ROOT, '..', 'ionic-core', 'dist', 'compiler');
|
||||
const coreDir = join(PROJECT_ROOT, '..', 'ionic-core', 'dist', 'compiled-ionic-angular');
|
||||
|
||||
const includeGlob = [join(ionicAngularDir, '**', '*.ts')];
|
||||
const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
|
||||
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||
|
||||
createTempTsConfig(includeGlob, ES_2015, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
|
||||
|
||||
const sassConfigPath = join('scripts', 'e2e', 'sass.config.js');
|
||||
const copyConfigPath = join('scripts', 'e2e', 'copy.config.js');
|
||||
|
||||
const appNgModulePath = join(dirname(appEntryPoint), 'app.module.ts');
|
||||
const distDir = join(distTestRoot, 'www');
|
||||
|
||||
return runAppScriptsBuild(appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, coreCompilerFilePath, coreDir, sassConfigPath, copyConfigPath, argv.dev).then(() => {
|
||||
const end = Date.now();
|
||||
console.log(`${filePath} took a total of ${(end - start) / 1000} seconds to build`);
|
||||
}).catch((err) => {
|
||||
console.log(`${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
function copyProtractorTestContent(filePaths: string[]): Promise<any> {
|
||||
const e2eTestPaths = filePaths.map(filePath => {
|
||||
return join(dirname(dirname(filePath)), 'e2e.ts');
|
||||
});
|
||||
return readE2ETestFiles(e2eTestPaths)
|
||||
.then((map: Map<string, string>) => {
|
||||
return applyTemplate(map);
|
||||
}).then((map: Map<string, string>) => {
|
||||
writeE2EJsFiles(map);
|
||||
});
|
||||
}
|
||||
|
||||
function applyTemplate(filePathContent: Map<string, string>) {
|
||||
const buildConfig = require(join('..', '..', 'build', 'config'));
|
||||
const templateFileContent = readFileSync(join(SCRIPTS_ROOT, 'e2e', 'e2e.template.js'));
|
||||
const templater = template(templateFileContent.toString());
|
||||
const modifiedMap = new Map<string, string>();
|
||||
const platforms = ['android', 'ios', 'windows'];
|
||||
filePathContent.forEach((fileContent: string, filePath: string) => {
|
||||
const srcRelativePath = relative(SRC_ROOT, dirname(filePath));
|
||||
const wwwRelativePath = join(srcRelativePath, 'www');
|
||||
platforms.forEach(platform => {
|
||||
const platformContents = templater({
|
||||
contents: fileContent,
|
||||
buildConfig: buildConfig,
|
||||
relativePath: wwwRelativePath,
|
||||
platform: platform,
|
||||
relativePathBackwardsCompatibility: dirname(wwwRelativePath)
|
||||
});
|
||||
const newFilePath = join(wwwRelativePath, `${platform}.e2e.js`);
|
||||
modifiedMap.set(newFilePath, platformContents);
|
||||
});
|
||||
});
|
||||
return modifiedMap;
|
||||
}
|
||||
|
||||
function writeE2EJsFiles(map: Map<string, string>) {
|
||||
const promises: Promise<any>[] = [];
|
||||
map.forEach((fileContent: string, filePath: string) => {
|
||||
const destination = join(process.cwd(), 'dist', 'e2e', filePath);
|
||||
promises.push(writeFileAsync(destination, fileContent));
|
||||
});
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
|
||||
function readE2ETestFiles(mainFilePaths: string[]): Promise<Map<string, string>> {
|
||||
const e2eFiles = mainFilePaths.map(mainFilePath => {
|
||||
return join(dirname(mainFilePath), 'e2e.ts');
|
||||
});
|
||||
|
||||
const promises: Promise<any>[] = [];
|
||||
const map = new Map<string, string>();
|
||||
for (const e2eFile of e2eFiles) {
|
||||
const promise = readE2EFile(e2eFile);
|
||||
promises.push(promise);
|
||||
promise.then((content: string) => {
|
||||
map.set(e2eFile, content);
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
return map;
|
||||
});
|
||||
}
|
||||
|
||||
function readE2EFile(filePath: string) {
|
||||
return readFileAsync(filePath).then((content: string) => {
|
||||
// purge the import statement at the top
|
||||
const purgeImportRegex = /.*?import.*?'protractor';/g;
|
||||
return content.replace(purgeImportRegex, '');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
task('e2e.clean', (done: Function) => {
|
||||
// this is a super hack, but it works for now
|
||||
if (argv.skipClean) {
|
||||
return done();
|
||||
}
|
||||
|
||||
del(['dist/e2e/**']).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
task('e2e.polyfill', (done: Function) => {
|
||||
if (argv.skipPolyfill) {
|
||||
return done();
|
||||
}
|
||||
|
||||
writePolyfills(join('dist', 'e2e', 'polyfills')).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
task('e2e.openProd', (done: Function) => {
|
||||
runSequence('e2e.prod', 'e2e.open', (err: any) => done(err));
|
||||
});
|
||||
|
||||
task('e2e.open', (done: Function) => {
|
||||
const folderInfo = getFolderInfo();
|
||||
if (folderInfo && folderInfo.componentName && folderInfo.componentTest) {
|
||||
const filePath = join(DIST_E2E_COMPONENTS_ROOT, folderInfo.componentName, 'test', folderInfo.componentTest, 'www', 'index.html');
|
||||
const spawnedCommand = spawn('open', [filePath]);
|
||||
|
||||
spawnedCommand.on('close', (code: number) => {
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
console.log(`Can't open without folder argument.`);
|
||||
}
|
||||
});
|
25
packages/ionic-angular/scripts/gulp/tasks/lint.ts
Normal file
25
packages/ionic-angular/scripts/gulp/tasks/lint.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { task, src } from 'gulp';
|
||||
import * as scsslint from 'gulp-scss-lint';
|
||||
import * as tslint from 'gulp-tslint';
|
||||
|
||||
task('lint', ['lint.sass', 'lint.ts']);
|
||||
|
||||
task('lint.ts', () => {
|
||||
return src([
|
||||
'src/**/*.ts'
|
||||
]).pipe(tslint({
|
||||
formatter: 'verbose'
|
||||
}))
|
||||
.pipe(tslint.report());
|
||||
});
|
||||
|
||||
task('lint.sass', function() {
|
||||
return src([
|
||||
'src/**/*.scss',
|
||||
'!src/components/*/test/**/*',
|
||||
'!src/util/test/*',
|
||||
'!src/themes/normalize.scss',
|
||||
])
|
||||
.pipe(scsslint())
|
||||
.pipe(scsslint.failReporter());
|
||||
});
|
12
packages/ionic-angular/scripts/gulp/tasks/polyfill.source.ts
Normal file
12
packages/ionic-angular/scripts/gulp/tasks/polyfill.source.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { task } from 'gulp';
|
||||
import { writePolyfills } from '../util';
|
||||
import { join } from 'path';
|
||||
|
||||
|
||||
task('src.polyfill', (done: Function) => {
|
||||
writePolyfills(join('scripts', 'polyfills')).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
18
packages/ionic-angular/scripts/gulp/tasks/polyfill.ts
Normal file
18
packages/ionic-angular/scripts/gulp/tasks/polyfill.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { task, src, dest } from 'gulp';
|
||||
import { writePolyfills } from '../util';
|
||||
import { join } from 'path';
|
||||
|
||||
task('polyfill', ['polyfill.copy-readme', 'polyfill.write']);
|
||||
|
||||
task('polyfill.write', (done: Function) => {
|
||||
writePolyfills(join('dist', 'ionic-angular', 'polyfills')).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
task('polyfill.copy-readme', (done: Function) => {
|
||||
return src(join('scripts', 'polyfill', 'readme.md'))
|
||||
.pipe(dest(join('dist', 'ionic-angular', 'polyfills')), done);
|
||||
});
|
330
packages/ionic-angular/scripts/gulp/tasks/release.ts
Normal file
330
packages/ionic-angular/scripts/gulp/tasks/release.ts
Normal file
@ -0,0 +1,330 @@
|
||||
import { exec, spawnSync, spawn } from 'child_process';
|
||||
import { writeFileSync } from 'fs';
|
||||
import * as changelog from 'conventional-changelog';
|
||||
import * as GithubApi from 'github';
|
||||
import { dest, src, start, task } from 'gulp';
|
||||
import { prompt } from 'inquirer';
|
||||
import { rollup } from 'rollup';
|
||||
import * as commonjs from 'rollup-plugin-commonjs';
|
||||
import * as nodeResolve from 'rollup-plugin-node-resolve';
|
||||
import * as runSequence from 'run-sequence';
|
||||
import * as semver from 'semver';
|
||||
import { obj } from 'through2';
|
||||
|
||||
import { DIST_BUILD_UMD_BUNDLE_ENTRYPOINT, DIST_BUILD_ROOT, DIST_BUNDLE_ROOT, PROJECT_ROOT, SCRIPTS_ROOT, SRC_ROOT } from '../constants';
|
||||
import { compileSass, copyFonts, createTimestamp, setSassIonicVersion, writePolyfills } from '../util';
|
||||
|
||||
var promptAnswers;
|
||||
|
||||
// Nightly: releases a nightly version
|
||||
task('nightly', (done: (err: any) => void) => {
|
||||
runSequence('release.pullLatest',
|
||||
'validate',
|
||||
'release.prepareReleasePackage',
|
||||
'release.publishNightly',
|
||||
done);
|
||||
});
|
||||
|
||||
// Release: prompt, update, publish
|
||||
task('release', (done: (err: any) => void) => {
|
||||
runSequence('release.pullLatest',
|
||||
'validate',
|
||||
'release.prepareReleasePackage',
|
||||
'release.promptVersion',
|
||||
'release.update',
|
||||
'release.publish',
|
||||
done);
|
||||
});
|
||||
|
||||
// Release.test: prompt and update
|
||||
task('release.test', (done: (err: any) => void) => {
|
||||
runSequence('validate',
|
||||
'release.prepareReleasePackage',
|
||||
'release.promptVersion',
|
||||
'release.update',
|
||||
done);
|
||||
});
|
||||
|
||||
// Release.update: update package.json and changelog
|
||||
task('release.update', (done: (err: any) => void) => {
|
||||
if (promptAnswers.confirmRelease === 'yes') {
|
||||
runSequence('release.copyProdVersion',
|
||||
'release.prepareChangelog',
|
||||
done);
|
||||
} else {
|
||||
console.log('Did not run release.update tasks, aborted release');
|
||||
done(null);
|
||||
}
|
||||
});
|
||||
|
||||
// Release.publish: publish to GitHub and npm
|
||||
task('release.publish', (done: (err: any) => void) => {
|
||||
if (promptAnswers.confirmRelease === 'yes') {
|
||||
runSequence('release.publishNpmRelease',
|
||||
'release.publishGithubRelease',
|
||||
done);
|
||||
} else {
|
||||
console.log('Did not run release.publish tasks, aborted release');
|
||||
done(null);
|
||||
}
|
||||
});
|
||||
|
||||
task('release.publishGithubRelease', (done: Function) => {
|
||||
const packageJSON = require('../../../package.json');
|
||||
|
||||
const github = new GithubApi({
|
||||
version: '3.0.0'
|
||||
});
|
||||
|
||||
github.authenticate({
|
||||
type: 'oauth',
|
||||
token: process.env.GH_TOKEN
|
||||
});
|
||||
|
||||
return changelog({
|
||||
preset: 'angular'
|
||||
})
|
||||
.pipe(obj(function(file, enc, cb){
|
||||
github.releases.createRelease({
|
||||
owner: 'ionic-team',
|
||||
repo: 'ionic',
|
||||
target_commitish: 'master',
|
||||
tag_name: 'v' + packageJSON.version,
|
||||
name: packageJSON.version,
|
||||
body: file.toString(),
|
||||
prerelease: false
|
||||
}, done);
|
||||
}));
|
||||
});
|
||||
|
||||
task('release.publishNpmRelease', (done: Function) => {
|
||||
const npmCmd = spawn('npm', ['publish', DIST_BUILD_ROOT]);
|
||||
npmCmd.stdout.on('data', function (data) {
|
||||
console.log(data.toString());
|
||||
});
|
||||
|
||||
npmCmd.stderr.on('data', function (data) {
|
||||
console.log('npm err: ' + data.toString());
|
||||
});
|
||||
|
||||
npmCmd.on('close', function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
task('release.promptVersion', (done: Function) => {
|
||||
prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'release',
|
||||
message: 'What type of release is this?',
|
||||
choices: [
|
||||
{
|
||||
name: 'Major: Incompatible API changes',
|
||||
value: 'major'
|
||||
}, {
|
||||
name: 'Minor: Backwards-compatible functionality',
|
||||
value: 'minor'
|
||||
}, {
|
||||
name: 'Patch: Backwards-compatible bug fixes',
|
||||
value: 'patch'
|
||||
}, {
|
||||
name: 'Premajor',
|
||||
value: 'premajor'
|
||||
}, {
|
||||
name: 'Preminor',
|
||||
value: 'preminor'
|
||||
}, {
|
||||
name: 'Prepatch',
|
||||
value: 'prepatch'
|
||||
}, {
|
||||
name: 'Prerelease',
|
||||
value: 'prerelease'
|
||||
}
|
||||
]
|
||||
}, {
|
||||
type: 'list',
|
||||
name: 'confirmRelease',
|
||||
default: 'no',
|
||||
choices: [
|
||||
{
|
||||
name: 'Yes',
|
||||
value: 'yes'
|
||||
}, {
|
||||
name: 'Abort release',
|
||||
value: 'no'
|
||||
}
|
||||
],
|
||||
message: function(answers) {
|
||||
var SEP = '---------------------------------';
|
||||
console.log('\n' + SEP + '\n' + getVersion(answers) + '\n' + SEP + '\n');
|
||||
return 'Are you sure you want to proceed with the release version above?';
|
||||
}
|
||||
}
|
||||
]).then(function (answers) {
|
||||
// Continue with the release if version was confirmed
|
||||
promptAnswers = answers;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
function getVersion(answers) {
|
||||
const sourcePackageJSON = require(`${PROJECT_ROOT}/package.json`);
|
||||
|
||||
return semver.inc(sourcePackageJSON.version, answers.release, true);
|
||||
}
|
||||
|
||||
task('release.copyProdVersion', () => {
|
||||
// Increment the version and update the source package file
|
||||
const sourcePackageJSON = require(`${PROJECT_ROOT}/package.json`);
|
||||
|
||||
sourcePackageJSON.version = semver.inc(sourcePackageJSON.version, promptAnswers.release, true);
|
||||
|
||||
const sourcePrettyPrintedJson = JSON.stringify(sourcePackageJSON, null, 2);
|
||||
writeFileSync(`${PROJECT_ROOT}/package.json`, sourcePrettyPrintedJson);
|
||||
|
||||
// Copy the source package version and update it in the build package file
|
||||
const packageJsonToUpdate = require(`${DIST_BUILD_ROOT}/package.json`);
|
||||
|
||||
packageJsonToUpdate.version = sourcePackageJSON.version;
|
||||
|
||||
const prettyPrintedJson = JSON.stringify(packageJsonToUpdate, null, 2);
|
||||
writeFileSync(`${DIST_BUILD_ROOT}/package.json`, prettyPrintedJson);
|
||||
});
|
||||
|
||||
task('release.prepareReleasePackage', (done: (err: any) => void) => {
|
||||
runSequence('clean',
|
||||
'core',
|
||||
'release.polyfill',
|
||||
'compile.release',
|
||||
'release.copyTemplates',
|
||||
'release.copyNpmInfo',
|
||||
'release.preparePackageJsonTemplate',
|
||||
'release.nightlyPackageJson',
|
||||
'release.compileSass',
|
||||
'release.fonts',
|
||||
'release.sass',
|
||||
'release.createUmdBundle',
|
||||
done);
|
||||
});
|
||||
|
||||
task('release.createUmdBundle', (done: Function) => {
|
||||
return rollup({
|
||||
entry: DIST_BUILD_UMD_BUNDLE_ENTRYPOINT,
|
||||
plugins: [
|
||||
nodeResolve({
|
||||
module: true,
|
||||
jsnext: true,
|
||||
main: true
|
||||
}),
|
||||
commonjs()
|
||||
]
|
||||
}).then((bundle) => {
|
||||
return bundle.write({
|
||||
format: 'umd',
|
||||
moduleName: 'ionicBundle',
|
||||
dest: `${DIST_BUNDLE_ROOT}/ionic.umd.js`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
task('release.polyfill', (done: Function) => {
|
||||
writePolyfills('dist/ionic-angular/polyfills').then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
task('release.publishNightly', (done: Function) => {
|
||||
const npmCmd = spawn('npm', ['publish', '--tag=nightly', DIST_BUILD_ROOT]);
|
||||
npmCmd.stdout.on('data', function (data) {
|
||||
console.log(data.toString());
|
||||
});
|
||||
|
||||
npmCmd.stderr.on('data', function (data) {
|
||||
console.log('npm err: ' + data.toString());
|
||||
});
|
||||
|
||||
npmCmd.on('close', function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
task('release.compileSass', () => {
|
||||
return compileSass(`${DIST_BUILD_ROOT}/css`);
|
||||
});
|
||||
|
||||
task('release.fonts', () => {
|
||||
return copyFonts(`${DIST_BUILD_ROOT}/fonts`);
|
||||
});
|
||||
|
||||
task('release.sass', () => {
|
||||
return src([`${SRC_ROOT}/**/*.scss`, `!${SRC_ROOT}/components/*/test/**/*`, `!${SRC_ROOT}/util/test/*`]).pipe(dest(`${DIST_BUILD_ROOT}`));
|
||||
});
|
||||
|
||||
task('release.pullLatest', (done: Function) => {
|
||||
exec('git status --porcelain', (err: Error, stdOut: string) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
} else if ( stdOut && stdOut.length > 0) {
|
||||
done(new Error('There are uncommited changes. Please commit or stash changes.'));
|
||||
} else {
|
||||
const gitPullResult = spawnSync('git', ['pull', 'origin', 'master']);
|
||||
if (gitPullResult.status !== 0) {
|
||||
done(new Error('Error running git pull'));
|
||||
}
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
task('release.prepareChangelog', () => {
|
||||
const changelog = require('gulp-conventional-changelog');
|
||||
return src(`${PROJECT_ROOT}/CHANGELOG.md`)
|
||||
.pipe(changelog({
|
||||
preset: 'angular'
|
||||
}))
|
||||
.pipe(dest(`${PROJECT_ROOT}`));
|
||||
});
|
||||
|
||||
task('release.copyTemplates', () => {
|
||||
return src([`${SCRIPTS_ROOT}/templates/**/*`]).pipe(dest(`${DIST_BUILD_ROOT}/templates`));
|
||||
});
|
||||
|
||||
task('release.copyNpmInfo', () => {
|
||||
return src([`${PROJECT_ROOT}/scripts/npm/.npmignore`, `${PROJECT_ROOT}/scripts/npm/README.md`]).pipe(dest(DIST_BUILD_ROOT));
|
||||
});
|
||||
|
||||
task('release.preparePackageJsonTemplate', () => {
|
||||
let templatePackageJSON = require(`${PROJECT_ROOT}/scripts/npm/package.json`);
|
||||
const sourcePackageJSON = require(`${PROJECT_ROOT}/package.json`);
|
||||
// copy source package.json data to template
|
||||
templatePackageJSON.version = sourcePackageJSON.version;
|
||||
templatePackageJSON.description = sourcePackageJSON.description;
|
||||
templatePackageJSON.keywords = sourcePackageJSON.keywords;
|
||||
|
||||
// copy source dependencies versions to the template's peerDependencies
|
||||
// only copy dependencies that show up as peerDependencies in the template
|
||||
for (let dependency in sourcePackageJSON.dependencies) {
|
||||
|
||||
// if the dependency is in both, AND the value of the entry is empty, copy it over
|
||||
if (dependency in templatePackageJSON.peerDependencies && templatePackageJSON.peerDependencies[dependency] === '') {
|
||||
templatePackageJSON.peerDependencies[dependency] = sourcePackageJSON.dependencies[dependency];
|
||||
}
|
||||
}
|
||||
|
||||
writeFileSync(`${DIST_BUILD_ROOT}` + '/package.json', JSON.stringify(templatePackageJSON, null, 2));
|
||||
});
|
||||
|
||||
task('release.nightlyPackageJson', () => {
|
||||
const packageJson: any = require(`${DIST_BUILD_ROOT}/package.json`);
|
||||
|
||||
packageJson.version = packageJson.version.split('-')
|
||||
.slice(0, 2)
|
||||
.concat(createTimestamp())
|
||||
.join('-');
|
||||
|
||||
writeFileSync(`${DIST_BUILD_ROOT}/package.json`, JSON.stringify(packageJson, null, 2));
|
||||
setSassIonicVersion(packageJson.version);
|
||||
});
|
119
packages/ionic-angular/scripts/gulp/tasks/snapshot.ts
Normal file
119
packages/ionic-angular/scripts/gulp/tasks/snapshot.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import { spawn } from 'child_process';
|
||||
import { createServer } from 'http';
|
||||
import { join, resolve } from 'path';
|
||||
|
||||
import * as connect from 'connect';
|
||||
import { task } from 'gulp';
|
||||
import * as serveStatic from 'serve-static';
|
||||
import { argv } from 'yargs';
|
||||
|
||||
import { DIST_E2E_COMPONENTS_ROOT, PROJECT_ROOT, SCRIPTS_ROOT } from '../constants';
|
||||
import { mergeObjects } from '../util';
|
||||
|
||||
|
||||
task('snapshot', ['e2e.prod'], (done: Function) => {
|
||||
snapshot(false, done);
|
||||
});
|
||||
|
||||
task('snapshot.skipBuild', (done: Function) => {
|
||||
snapshot(false, done);
|
||||
});
|
||||
|
||||
function snapshot(quickMode: boolean, callback: Function) {
|
||||
const snapshotConfig = require('../../snapshot/snapshot.config').config;
|
||||
const protractorConfigFile = resolve(SCRIPTS_ROOT, 'snapshot/protractor.config.js');
|
||||
|
||||
const snapshotDefaults = snapshotConfig.platformDefaults || {};
|
||||
const snapshotValues: any = mergeObjects(snapshotDefaults, argv || {});
|
||||
|
||||
if (!snapshotConfig.accessKey || !snapshotConfig.accessKey.length) {
|
||||
console.error('Missing IONIC_SNAPSHOT_KEY environment variable');
|
||||
return callback(new Error('Missing IONIC_SNAPSHOT_KEY environment variable'));
|
||||
}
|
||||
|
||||
let component = '*';
|
||||
let e2eSpecs = '*';
|
||||
|
||||
const folderArg: string = argv.folder || argv.f;
|
||||
if (folderArg && folderArg.length) {
|
||||
const folderArgPaths = folderArg.split('/');
|
||||
component = folderArgPaths[0];
|
||||
if (folderArgPaths.length > 1) {
|
||||
e2eSpecs = folderArgPaths[1];
|
||||
}
|
||||
}
|
||||
|
||||
const specs = join(DIST_E2E_COMPONENTS_ROOT, component, 'test', e2eSpecs, 'www', '*e2e.js');
|
||||
|
||||
console.log('[snapshot] Running with', 'Production', 'build');
|
||||
console.log(`[snapshot] Specs: ${specs}`);
|
||||
|
||||
const testId = generateTestId();
|
||||
console.log(`[snapshot] TestId: ${testId}`);
|
||||
|
||||
snapshotValues.params.test_id = testId;
|
||||
snapshotValues.params.upload = !quickMode;
|
||||
|
||||
var protractorArgs = [
|
||||
'--browser ' + snapshotValues.browser,
|
||||
'--platform ' + snapshotValues.platform,
|
||||
'--params.platform_id=' + snapshotValues.params.platform_id,
|
||||
'--params.platform_index=' + snapshotValues.params.platform_index,
|
||||
'--params.platform_count=' + snapshotValues.params.platform_count,
|
||||
'--params.width=' + snapshotValues.params.width,
|
||||
'--params.height=' + snapshotValues.params.height,
|
||||
'--params.test_id=' + snapshotValues.params.test_id,
|
||||
'--params.upload=' + snapshotValues.params.upload,
|
||||
'--specs=' + specs
|
||||
];
|
||||
|
||||
return protractor(callback, [protractorConfigFile].concat(protractorArgs), testId);
|
||||
}
|
||||
|
||||
function protractor(callback, args, testId: string) {
|
||||
const buildConfig = require('../../build/config');
|
||||
const app = connect().use(serveStatic(PROJECT_ROOT));
|
||||
const protractorHttpServer = createServer(app).listen(buildConfig.protractorPort);
|
||||
|
||||
console.log(`Serving ${process.cwd()} on http://localhost:${buildConfig.protractorPort}`);
|
||||
|
||||
let spawnCommand = process.platform === 'win32' ? 'protractor.cmd' : 'protractor';
|
||||
|
||||
const child = spawn(spawnCommand, args, {
|
||||
stdio: [process.stdin, process.stdout, 'pipe']
|
||||
});
|
||||
|
||||
let errored = false;
|
||||
let callbackCalled = false;
|
||||
|
||||
child.stderr.on('data', function(data) {
|
||||
protractorHttpServer.close();
|
||||
console.error(data.toString());
|
||||
if (!errored) {
|
||||
errored = true;
|
||||
if (!callbackCalled) {
|
||||
callback('Protractor tests failed.');
|
||||
callbackCalled = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
child.on('exit', function() {
|
||||
protractorHttpServer.close();
|
||||
if (!callbackCalled) {
|
||||
console.log(`[snapshot] TestId: ${testId}`);
|
||||
callback();
|
||||
callbackCalled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function generateTestId() {
|
||||
let chars = 'abcdefghjkmnpqrstuvwxyz';
|
||||
let id = chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
chars += '0123456789';
|
||||
while (id.length < 3) {
|
||||
id += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return id;
|
||||
}
|
130
packages/ionic-angular/scripts/gulp/tasks/test.ts
Normal file
130
packages/ionic-angular/scripts/gulp/tasks/test.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import { join } from 'path';
|
||||
import { dest, src, task } from 'gulp';
|
||||
import { DIST_VENDOR_ROOT, NPM_VENDOR_FILES, PROJECT_ROOT, SCRIPTS_ROOT } from '../constants';
|
||||
|
||||
task('test', ['test.assembleVendorJs', 'compile.karma'], (done: Function) => {
|
||||
karmaTest(false, done);
|
||||
});
|
||||
|
||||
task('test.fast', ['compile.karma'], (done: Function) => {
|
||||
karmaTest(false, done);
|
||||
});
|
||||
|
||||
task('test.watch', ['test.assembleVendorJs', 'compile.karma'], (done: Function) => {
|
||||
karmaTest(true, done);
|
||||
});
|
||||
|
||||
task('test.coverage', ['test.assembleVendorJs', 'compile.karma'], (done: Function) => {
|
||||
karmaTest(false, () => {
|
||||
createKarmaCoverageReport(done);
|
||||
});
|
||||
});
|
||||
|
||||
task('test.imageserver', () => {
|
||||
const http = require('http');
|
||||
const url = require('url');
|
||||
const port = 8900;
|
||||
const requestedUrls = [];
|
||||
let start = Date.now();
|
||||
|
||||
function handleRequest(req, res) {
|
||||
const urlParse = url.parse(req.url, true);
|
||||
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
res.setHeader('Age', '0');
|
||||
res.setHeader('cache-control', 'no-store');
|
||||
|
||||
if (urlParse.pathname === '/reset') {
|
||||
console.log('Image Server Reset');
|
||||
console.log('---------------------------');
|
||||
requestedUrls.length = 0;
|
||||
start = Date.now();
|
||||
res.setHeader('Content-Type', 'text/plain');
|
||||
res.end('reset');
|
||||
return;
|
||||
}
|
||||
|
||||
const delay = urlParse.query.d || 1000;
|
||||
const id = urlParse.query.id || Math.round(Math.random() * 1000);
|
||||
const width = urlParse.query.w || 80;
|
||||
const height = urlParse.query.h || 80;
|
||||
const color = urlParse.query.c || 'yellow';
|
||||
|
||||
requestedUrls.push(req.url);
|
||||
|
||||
console.log(`id: ${id}, requested: ${requestedUrls.filter(f => f === req.url).length}, timestamp: ${Date.now() - start}`);
|
||||
|
||||
setTimeout(() => {
|
||||
res.setHeader('Content-Type', 'image/svg+xml');
|
||||
res.end(`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 ${width} ${height}" style="background-color: ${color};">
|
||||
<text x="5" y="22" style="font-family: Courier; font-size: 24px">${id}</text>
|
||||
</svg>`);
|
||||
}, delay);
|
||||
}
|
||||
|
||||
http.globalAgent.maxSockets = 1;
|
||||
|
||||
http.createServer(handleRequest).listen(port, () => {
|
||||
console.log(` Mock image server listening on: http://localhost:${port}/?d=2000&id=99`);
|
||||
console.log(` Possible querystrings:`);
|
||||
console.log(` id: the text to go in the svg image, defaults to a random number`);
|
||||
console.log(` d: how many milliseconds it should take to respond, defaults to 1000`);
|
||||
console.log(` w: image width, defaults to 80`);
|
||||
console.log(` h: image height, defaults to 80`);
|
||||
console.log(` c: image color, defaults to yellow`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function karmaTest(watch: boolean, done: Function) {
|
||||
const karma = require('karma');
|
||||
const argv = require('yargs').argv;
|
||||
|
||||
let karmaConfig = {
|
||||
configFile: join(SCRIPTS_ROOT, 'karma/karma.conf.js'),
|
||||
singleRun: true,
|
||||
};
|
||||
|
||||
if (watch) {
|
||||
(karmaConfig as any).singleRun = false;
|
||||
}
|
||||
|
||||
if (argv.testGrep) {
|
||||
(<any>karmaConfig).client = {
|
||||
args: ['--grep', argv.testGrep]
|
||||
};
|
||||
}
|
||||
if (typeof argv.debug !== 'undefined') {
|
||||
karmaConfig.singleRun = false;
|
||||
}
|
||||
|
||||
new karma.Server(karmaConfig, done).start();
|
||||
}
|
||||
|
||||
|
||||
task('test.assembleVendorJs', () => {
|
||||
const files = NPM_VENDOR_FILES.map((root) => {
|
||||
const glob = join(root, '**/*.+(js|js.map)');
|
||||
return src(join('node_modules', glob))
|
||||
.pipe(dest(join(DIST_VENDOR_ROOT, root)));
|
||||
});
|
||||
const gulpMerge = require('merge2');
|
||||
return gulpMerge(files);
|
||||
});
|
||||
|
||||
|
||||
/* creates a karma code coverage report */
|
||||
function createKarmaCoverageReport(done: Function) {
|
||||
console.log('Generating Unit Test Coverage Report...');
|
||||
|
||||
let exec = require('child_process').exec;
|
||||
let command = `node_modules/.bin/remap-istanbul -i coverage/coverage-final.json -o coverage -t html`;
|
||||
|
||||
exec(command, function(err: any, stdout: any, stderr: any) {
|
||||
console.log(`file://${PROJECT_ROOT}/coverage/index.html`);
|
||||
done(err);
|
||||
});
|
||||
}
|
115
packages/ionic-angular/scripts/gulp/tasks/theme.ts
Normal file
115
packages/ionic-angular/scripts/gulp/tasks/theme.ts
Normal file
@ -0,0 +1,115 @@
|
||||
import { task } from 'gulp';
|
||||
import { SRC_ROOT, SRC_COMPONENTS_ROOT } from '../constants';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
task('theme', (done: () => void) => {
|
||||
let opts: GenerateThemeOptions = {
|
||||
src: path.join(SRC_COMPONENTS_ROOT),
|
||||
dest: path.join(SRC_ROOT, 'ionic-generate.scss')
|
||||
};
|
||||
generateThemeSource(opts);
|
||||
});
|
||||
|
||||
|
||||
export function generateThemeSource(opts: GenerateThemeOptions) {
|
||||
console.log(`[theme] src: ${opts.src}`);
|
||||
console.log(`[theme] desc: ${opts.dest}`);
|
||||
|
||||
let components = getSourceComponents(opts);
|
||||
generateManifest(opts, components);
|
||||
}
|
||||
|
||||
|
||||
function generateManifest(opts: GenerateThemeOptions, components: Component[]) {
|
||||
|
||||
components.forEach(c => {
|
||||
console.log(c.name);
|
||||
|
||||
c.modes.forEach(m => {
|
||||
console.log(` ${m.mode} ${m.src}`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getSourceComponents(opts: GenerateThemeOptions) {
|
||||
let components: Component[] = [];
|
||||
|
||||
function readFiles(src: string, fillFiles: string[]) {
|
||||
fs.readdirSync(src).forEach((file, index) => {
|
||||
var filePath = path.join(src, file);
|
||||
var fsStats = fs.statSync(filePath);
|
||||
if (fsStats.isDirectory()) {
|
||||
readFiles(filePath, fillFiles);
|
||||
} else if (fsStats.isFile()) {
|
||||
fillFiles.push(filePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let files: string[] = [];
|
||||
readFiles(opts.src, files);
|
||||
|
||||
files = files.filter(f => f.slice(-5) === '.scss');
|
||||
files.sort();
|
||||
|
||||
files.forEach(f => {
|
||||
var componentRoot = f.replace(opts.src + '/', '');
|
||||
var fileSplit = componentRoot.split('/');
|
||||
var componentName = fileSplit[0];
|
||||
var fileName = fileSplit[1];
|
||||
|
||||
var component = components.find(c => c.name === componentName);
|
||||
if (!component) {
|
||||
component = {
|
||||
name: componentName,
|
||||
modes: []
|
||||
};
|
||||
components.push(component);
|
||||
}
|
||||
|
||||
fileSplit = fileName.split('.');
|
||||
if (fileSplit.length === 3) {
|
||||
component.modes.push({
|
||||
src: f,
|
||||
mode: fileSplit[1]
|
||||
});
|
||||
|
||||
} else {
|
||||
component.modes.unshift({
|
||||
src: f,
|
||||
mode: DEFAULT_MODE
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
console.log(`[theme] components: ${components.length}`);
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
|
||||
export interface GenerateThemeOptions {
|
||||
src: string;
|
||||
dest: string;
|
||||
includeModes?: string[];
|
||||
excludeModes?: string[];
|
||||
includeComponents?: string[];
|
||||
excludeComponents?: string[];
|
||||
}
|
||||
|
||||
export interface Component {
|
||||
name: string;
|
||||
modes: FileDetails[];
|
||||
}
|
||||
|
||||
export interface FileDetails {
|
||||
src: string;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
const DEFAULT_MODE = '*';
|
Reference in New Issue
Block a user