You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1513 lines
45 KiB

10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
  1. /*
  2. All configurable options are defined in separate files inside the 'task/' folder
  3. Please adjust these files according to your personal requirements
  4. */
  5. /*******************************
  6. Set-up
  7. *******************************/
  8. var
  9. gulp = require('gulp-help')(require('gulp')),
  10. // node components & oddballs
  11. console = require('better-console'),
  12. del = require('del'),
  13. extend = require('extend'),
  14. fs = require('fs'),
  15. // unsure
  16. path = require('path'),
  17. // watch / build deps
  18. autoprefixer = require('gulp-autoprefixer'),
  19. chmod = require('gulp-chmod'),
  20. clone = require('gulp-clone'),
  21. concat = require('gulp-concat'),
  22. copy = require('gulp-copy'),
  23. debug = require('gulp-debug'),
  24. flatten = require('gulp-flatten'),
  25. header = require('gulp-header'),
  26. karma = require('gulp-karma'),
  27. less = require('gulp-less'),
  28. minifyCSS = require('gulp-minify-css'),
  29. plumber = require('gulp-plumber'),
  30. print = require('gulp-print'),
  31. rename = require('gulp-rename'),
  32. replace = require('gulp-replace'),
  33. uglify = require('gulp-uglify'),
  34. util = require('gulp-util'),
  35. watch = require('gulp-watch'),
  36. // rtl
  37. rtlcss = require('gulp-rtlcss'),
  38. // config
  39. banner = require('./tasks/banner'),
  40. comments = require('./tasks/comments'),
  41. defaults = require('./tasks/defaults'),
  42. log = require('./tasks/log'),
  43. settings = require('./tasks/gulp-settings'),
  44. // local
  45. runSetup = false,
  46. overwrite = true,
  47. config,
  48. package,
  49. github,
  50. version,
  51. // derived
  52. base,
  53. clean,
  54. output,
  55. source,
  56. assetPaths,
  57. componentGlob,
  58. // temporary
  59. folder
  60. ;
  61. /*******************************
  62. Read Settings
  63. *******************************/
  64. try {
  65. // try to load json
  66. var
  67. config = require(defaults.files.config),
  68. package = (fs.existsSync(defaults.files.npm))
  69. ? require(defaults.files.npm)
  70. : false
  71. ;
  72. }
  73. catch(error) {
  74. if(error.code === 'MODULE_NOT_FOUND') {
  75. console.error('No semantic.json config found');
  76. }
  77. var config = false;
  78. }
  79. /*******************************
  80. Values Derived From Config
  81. *******************************/
  82. var
  83. getConfigValues = function() {
  84. if(!config) {
  85. runSetup = true;
  86. config = defaults;
  87. }
  88. // extend defaults using shallow copy
  89. config = extend(false, {}, defaults, config);
  90. // shorthand
  91. base = config.base;
  92. clean = config.paths.clean;
  93. output = config.paths.output;
  94. source = config.paths.source;
  95. // npm package.json holds true "version"
  96. version = (package !== undefined)
  97. ? package.version || 'Unknown'
  98. : 'Unknown'
  99. ;
  100. // relative asset paths for css
  101. assetPaths = {
  102. uncompressed : path.relative(output.uncompressed, output.themes).replace(/\\/g,'/'),
  103. compressed : path.relative(output.compressed, output.themes).replace(/\\/g,'/'),
  104. packaged : path.relative(output.packaged, output.themes).replace(/\\/g,'/')
  105. };
  106. // add base path to all folders
  107. for(var folder in source) {
  108. if(source.hasOwnProperty(folder)) {
  109. source[folder] = path.normalize(base + source[folder]);
  110. }
  111. }
  112. for(folder in output) {
  113. if(output.hasOwnProperty(folder)) {
  114. output[folder] = path.normalize(base + output[folder]);
  115. }
  116. }
  117. clean = base + clean;
  118. // create glob for matching filenames from components in semantic.json
  119. componentGlob = (typeof config.components == 'object')
  120. ? (config.components.length > 1)
  121. ? '{' + config.components.join(',') + '}'
  122. : config.components[0]
  123. : '{' + defaults.components.join(',') + '}'
  124. ;
  125. }
  126. ;
  127. getConfigValues();
  128. /*******************************
  129. Tasks
  130. *******************************/
  131. gulp.task('default', false, [
  132. 'check install'
  133. ]);
  134. gulp.task('watch', 'Watch for site/theme changes (Default Task)', function(callback) {
  135. console.clear();
  136. console.log('Watching source files for changes');
  137. if(!fs.existsSync(config.files.theme)) {
  138. console.error('Cant compile LESS. Run "gulp install" to create a theme config file');
  139. return;
  140. }
  141. // start rtl task instead
  142. if(config.rtl) {
  143. gulp.start('watch rtl');
  144. return;
  145. }
  146. // watching changes in style
  147. gulp
  148. .watch([
  149. source.config,
  150. source.definitions + '**/*.less',
  151. source.site + '**/*.{overrides,variables}',
  152. source.themes + '**/*.{overrides,variables}'
  153. ], function(file) {
  154. var
  155. srcPath,
  156. stream,
  157. compressedStream,
  158. uncompressedStream,
  159. isDefinition,
  160. isPackagedTheme,
  161. isSiteTheme,
  162. isConfig
  163. ;
  164. gulp.src(file.path)
  165. .pipe(print(log.modified))
  166. ;
  167. // recompile on *.override , *.variable change
  168. isDefinition = (file.path.indexOf(source.definitions) !== -1);
  169. isPackagedTheme = (file.path.indexOf(source.themes) !== -1);
  170. isSiteTheme = (file.path.indexOf(source.site) !== -1);
  171. isConfig = (file.path.indexOf('.config') !== -1);
  172. if(isDefinition || isPackagedTheme || isSiteTheme) {
  173. // rebuild only matching definition file
  174. srcPath = util.replaceExtension(file.path, '.less');
  175. srcPath = srcPath.replace(config.regExp.themePath, source.definitions);
  176. srcPath = srcPath.replace(source.site, source.definitions);
  177. }
  178. else if(isConfig) {
  179. // impossible to tell which file was updated in theme.config, rebuild all
  180. console.log('Change detected in theme config');
  181. gulp.start('build');
  182. }
  183. else {
  184. srcPath = util.replaceExtension(file.path, '.less');
  185. }
  186. // get relative asset path (path returns wrong path? hardcoded)
  187. // assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
  188. assetPaths.source = '../../themes';
  189. if( fs.existsSync(srcPath) ) {
  190. // unified css stream
  191. stream = gulp.src(srcPath)
  192. .pipe(plumber())
  193. .pipe(less(settings.less))
  194. .pipe(replace(comments.variables.in, comments.variables.out))
  195. .pipe(replace(comments.large.in, comments.large.out))
  196. .pipe(replace(comments.small.in, comments.small.out))
  197. .pipe(replace(comments.tiny.in, comments.tiny.out))
  198. .pipe(autoprefixer(settings.prefix))
  199. ;
  200. // use 2 concurrent streams from same pipe
  201. uncompressedStream = stream.pipe(clone());
  202. compressedStream = stream.pipe(clone());
  203. uncompressedStream
  204. .pipe(plumber())
  205. .pipe(replace(assetPaths.source, assetPaths.uncompressed))
  206. .pipe(header(banner, settings.header))
  207. .pipe(chmod(config.permission))
  208. .pipe(gulp.dest(output.uncompressed))
  209. .pipe(print(log.created))
  210. .on('end', function() {
  211. gulp.start('package uncompressed css');
  212. })
  213. ;
  214. compressedStream = stream
  215. .pipe(plumber())
  216. .pipe(clone())
  217. .pipe(replace(assetPaths.source, assetPaths.compressed))
  218. .pipe(minifyCSS(settings.minify))
  219. .pipe(rename(settings.rename.minCSS))
  220. .pipe(header(banner, settings.header))
  221. .pipe(chmod(config.permission))
  222. .pipe(gulp.dest(output.compressed))
  223. .pipe(print(log.created))
  224. .on('end', function() {
  225. gulp.start('package compressed css');
  226. })
  227. ;
  228. }
  229. else {
  230. console.log('SRC Path Does Not Exist', srcPath);
  231. }
  232. })
  233. ;
  234. // watch for changes in assets that match component names (or their plural)
  235. gulp
  236. .watch([
  237. source.themes + '**/assets/**/' + componentGlob + '?(s).*'
  238. ], function(file) {
  239. // copy assets
  240. gulp.src(file.path, { base: source.themes })
  241. .pipe(chmod(config.permission))
  242. .pipe(gulp.dest(output.themes))
  243. .pipe(print(log.created))
  244. ;
  245. })
  246. ;
  247. // watch for changes in js
  248. gulp
  249. .watch([
  250. source.definitions + '**/*.js'
  251. ], function(file) {
  252. gulp.src(file.path)
  253. .pipe(plumber())
  254. .pipe(chmod(config.permission))
  255. .pipe(gulp.dest(output.uncompressed))
  256. .pipe(print(log.created))
  257. .pipe(uglify(settings.uglify))
  258. .pipe(rename(settings.rename.minJS))
  259. .pipe(chmod(config.permission))
  260. .pipe(gulp.dest(output.compressed))
  261. .pipe(print(log.created))
  262. .on('end', function() {
  263. gulp.start('package compressed js');
  264. gulp.start('package uncompressed js');
  265. })
  266. ;
  267. })
  268. ;
  269. });
  270. // Builds all files
  271. gulp.task('build', 'Builds all files from source', function(callback) {
  272. var
  273. stream,
  274. compressedStream,
  275. uncompressedStream
  276. ;
  277. console.info('Building Semantic');
  278. if(!fs.existsSync(config.files.theme)) {
  279. console.error('Cant build LESS. Run "gulp install" to create a theme config file');
  280. return;
  281. }
  282. // Run RTL build instead
  283. if(config.rtl) {
  284. gulp.start('build rtl');
  285. return;
  286. }
  287. // assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
  288. assetPaths.source = '../../themes'; // path.relative returns wrong path (hardcoded for src)
  289. // copy assets
  290. gulp.src(source.themes + '**/assets/**/' + componentGlob + '?(s).*')
  291. .pipe(chmod(config.permission))
  292. .pipe(gulp.dest(output.themes))
  293. ;
  294. // javascript stream
  295. gulp.src(source.definitions + '**/' + componentGlob + '.js')
  296. .pipe(plumber())
  297. .pipe(flatten())
  298. .pipe(chmod(config.permission))
  299. .pipe(gulp.dest(output.uncompressed))
  300. .pipe(print(log.created))
  301. .pipe(uglify(settings.uglify))
  302. .pipe(rename(settings.rename.minJS))
  303. .pipe(header(banner, settings.header))
  304. .pipe(chmod(config.permission))
  305. .pipe(gulp.dest(output.compressed))
  306. .pipe(print(log.created))
  307. .on('end', function() {
  308. gulp.start('package compressed js');
  309. gulp.start('package uncompressed js');
  310. })
  311. ;
  312. // unified css stream
  313. stream = gulp.src(source.definitions + '**/' + componentGlob + '.less')
  314. .pipe(plumber())
  315. .pipe(less(settings.less))
  316. .pipe(flatten())
  317. .pipe(replace(comments.variables.in, comments.variables.out))
  318. .pipe(replace(comments.large.in, comments.large.out))
  319. .pipe(replace(comments.small.in, comments.small.out))
  320. .pipe(replace(comments.tiny.in, comments.tiny.out))
  321. .pipe(autoprefixer(settings.prefix))
  322. ;
  323. // use 2 concurrent streams from same source to concat release
  324. uncompressedStream = stream.pipe(clone());
  325. compressedStream = stream.pipe(clone());
  326. uncompressedStream
  327. .pipe(plumber())
  328. .pipe(replace(assetPaths.source, assetPaths.uncompressed))
  329. .pipe(header(banner, settings.header))
  330. .pipe(chmod(config.permission))
  331. .pipe(gulp.dest(output.uncompressed))
  332. .pipe(print(log.created))
  333. .on('end', function() {
  334. gulp.start('package uncompressed css');
  335. })
  336. ;
  337. compressedStream = stream
  338. .pipe(plumber())
  339. .pipe(clone())
  340. .pipe(replace(assetPaths.source, assetPaths.compressed))
  341. .pipe(minifyCSS(settings.minify))
  342. .pipe(rename(settings.rename.minCSS))
  343. .pipe(header(banner, settings.header))
  344. .pipe(chmod(config.permission))
  345. .pipe(gulp.dest(output.compressed))
  346. .pipe(print(log.created))
  347. .on('end', function() {
  348. callback();
  349. gulp.start('package compressed css');
  350. })
  351. ;
  352. });
  353. // cleans distribution files
  354. gulp.task('clean', 'Clean dist folder', function(callback) {
  355. return del([clean], settings.del, callback);
  356. });
  357. gulp.task('version', 'Displays current version of Semantic', function(callback) {
  358. console.log('Semantic UI ' + version);
  359. });
  360. /*******************************
  361. RTL Tasks
  362. *******************************/
  363. /* Watch RTL */
  364. gulp.task('watch rtl', 'Watch for site/theme changes (Default Task)', function(callback) {
  365. console.clear();
  366. console.log('Watching RTL source files for changes');
  367. if(!fs.existsSync(config.files.theme)) {
  368. console.error('Cant compile LESS. Run "gulp install" to create a theme config file');
  369. return;
  370. }
  371. // watching changes in style
  372. gulp
  373. .watch([
  374. source.config,
  375. source.definitions + '**/*.less',
  376. source.site + '**/*.{overrides,variables}',
  377. source.themes + '**/*.{overrides,variables}'
  378. ], function(file) {
  379. var
  380. srcPath,
  381. stream,
  382. compressedStream,
  383. uncompressedStream,
  384. isDefinition,
  385. isPackagedTheme,
  386. isSiteTheme,
  387. isConfig
  388. ;
  389. gulp.src(file.path)
  390. .pipe(print(log.modified))
  391. ;
  392. // recompile on *.override , *.variable change
  393. isDefinition = (file.path.indexOf(source.definitions) !== -1);
  394. isPackagedTheme = (file.path.indexOf(source.themes) !== -1);
  395. isSiteTheme = (file.path.indexOf(source.site) !== -1);
  396. isConfig = (file.path.indexOf('.config') !== -1);
  397. if(isDefinition || isPackagedTheme || isSiteTheme) {
  398. srcPath = util.replaceExtension(file.path, '.less');
  399. srcPath = srcPath.replace(config.regExp.themePath, source.definitions);
  400. srcPath = srcPath.replace(source.site, source.definitions);
  401. }
  402. else if(isConfig) {
  403. console.log('Change detected in theme config');
  404. gulp.start('build');
  405. }
  406. else {
  407. srcPath = util.replaceExtension(file.path, '.less');
  408. }
  409. // get relative asset path (path returns wrong path? hardcoded)
  410. // assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
  411. assetPaths.source = '../../themes';
  412. if( fs.existsSync(srcPath) ) {
  413. // unified css stream
  414. stream = gulp.src(srcPath)
  415. .pipe(plumber())
  416. .pipe(less(settings.less))
  417. .pipe(replace(comments.variables.in, comments.variables.out))
  418. .pipe(replace(comments.large.in, comments.large.out))
  419. .pipe(replace(comments.small.in, comments.small.out))
  420. .pipe(replace(comments.tiny.in, comments.tiny.out))
  421. .pipe(autoprefixer(settings.prefix))
  422. .pipe(rtlcss())
  423. ;
  424. // use 2 concurrent streams from same source
  425. uncompressedStream = stream.pipe(clone());
  426. compressedStream = stream.pipe(clone());
  427. uncompressedStream
  428. .pipe(plumber())
  429. .pipe(replace(assetPaths.source, assetPaths.uncompressed))
  430. .pipe(header(banner, settings.header))
  431. .pipe(chmod(config.permission))
  432. .pipe(rename(settings.rename.rtlCSS))
  433. .pipe(gulp.dest(output.uncompressed))
  434. .pipe(print(log.created))
  435. .on('end', function() {
  436. gulp.start('package uncompressed rtl css');
  437. })
  438. ;
  439. compressedStream = stream
  440. .pipe(plumber())
  441. .pipe(clone())
  442. .pipe(replace(assetPaths.source, assetPaths.compressed))
  443. .pipe(minifyCSS(settings.minify))
  444. .pipe(header(banner, settings.header))
  445. .pipe(chmod(config.permission))
  446. .pipe(rename(settings.rename.rtlMinCSS))
  447. .pipe(gulp.dest(output.compressed))
  448. .pipe(print(log.created))
  449. .on('end', function() {
  450. gulp.start('package compressed rtl css');
  451. })
  452. ;
  453. }
  454. else {
  455. console.log('SRC Path Does Not Exist', srcPath);
  456. }
  457. })
  458. ;
  459. // watch changes in assets
  460. gulp
  461. .watch([
  462. source.themes + '**/assets/**'
  463. ], function(file) {
  464. // copy assets
  465. gulp.src(file.path, { base: source.themes })
  466. .pipe(chmod(config.permission))
  467. .pipe(gulp.dest(output.themes))
  468. .pipe(print(log.created))
  469. ;
  470. })
  471. ;
  472. // watch changes in js
  473. gulp
  474. .watch([
  475. source.definitions + '**/*.js'
  476. ], function(file) {
  477. gulp.src(file.path)
  478. .pipe(plumber())
  479. .pipe(chmod(config.permission))
  480. .pipe(gulp.dest(output.uncompressed))
  481. .pipe(print(log.created))
  482. .pipe(uglify(settings.uglify))
  483. .pipe(rename(settings.rename.minJS))
  484. .pipe(chmod(config.permission))
  485. .pipe(gulp.dest(output.compressed))
  486. .pipe(print(log.created))
  487. .on('end', function() {
  488. gulp.start('package compressed js');
  489. gulp.start('package uncompressed js');
  490. })
  491. ;
  492. })
  493. ;
  494. });
  495. /* Build RTL */
  496. gulp.task('build rtl', 'Builds all files from source', function(callback) {
  497. var
  498. stream,
  499. compressedStream,
  500. uncompressedStream
  501. ;
  502. console.info('Building Semantic RTL');
  503. if(!fs.existsSync(config.files.theme)) {
  504. console.error('Cant build LESS. Run "gulp install" to create a theme config file');
  505. return;
  506. }
  507. // get relative asset path (path returns wrong path?)
  508. // assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
  509. assetPaths.source = '../../themes'; // hardcoded
  510. // copy assets
  511. gulp.src(source.themes + '**/assets/**')
  512. .pipe(chmod(config.permission))
  513. .pipe(gulp.dest(output.themes))
  514. ;
  515. // javascript stream
  516. gulp.src(source.definitions + '**/' + componentGlob + '.js')
  517. .pipe(plumber())
  518. .pipe(flatten())
  519. .pipe(chmod(config.permission))
  520. .pipe(gulp.dest(output.uncompressed))
  521. .pipe(print(log.created))
  522. .pipe(uglify(settings.uglify))
  523. .pipe(rename(settings.rename.minJS))
  524. .pipe(header(banner, settings.header))
  525. .pipe(chmod(config.permission))
  526. .pipe(gulp.dest(output.compressed))
  527. .pipe(print(log.created))
  528. .on('end', function() {
  529. gulp.start('package compressed js');
  530. gulp.start('package uncompressed js');
  531. })
  532. ;
  533. // unified css stream
  534. stream = gulp.src(source.definitions + '**/' + componentGlob + '.less')
  535. .pipe(plumber())
  536. .pipe(less(settings.less))
  537. .pipe(flatten())
  538. .pipe(replace(comments.variables.in, comments.variables.out))
  539. .pipe(replace(comments.large.in, comments.large.out))
  540. .pipe(replace(comments.small.in, comments.small.out))
  541. .pipe(replace(comments.tiny.in, comments.tiny.out))
  542. .pipe(autoprefixer(settings.prefix))
  543. .pipe(rtlcss())
  544. ;
  545. // use 2 concurrent streams from same source to concat release
  546. uncompressedStream = stream.pipe(clone());
  547. compressedStream = stream.pipe(clone());
  548. uncompressedStream
  549. .pipe(plumber())
  550. .pipe(replace(assetPaths.source, assetPaths.uncompressed))
  551. .pipe(rename(settings.rename.rtlCSS))
  552. .pipe(header(banner, settings.header))
  553. .pipe(chmod(config.permission))
  554. .pipe(gulp.dest(output.uncompressed))
  555. .pipe(print(log.created))
  556. .on('end', function() {
  557. gulp.start('package uncompressed rtl css');
  558. })
  559. ;
  560. compressedStream = stream
  561. .pipe(plumber())
  562. .pipe(clone())
  563. .pipe(replace(assetPaths.source, assetPaths.compressed))
  564. .pipe(minifyCSS(settings.minify))
  565. .pipe(rename(settings.rename.rtlMinCSS))
  566. .pipe(header(banner, settings.header))
  567. .pipe(chmod(config.permission))
  568. .pipe(gulp.dest(output.compressed))
  569. .pipe(print(log.created))
  570. .on('end', function() {
  571. callback();
  572. gulp.start('package compressed rtl css');
  573. })
  574. ;
  575. });
  576. gulp.task('package uncompressed rtl css', false, function () {
  577. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).rtl.css')
  578. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  579. .pipe(concatCSS('semantic.rtl.css'))
  580. .pipe(gulp.dest(output.packaged))
  581. .pipe(print(log.created))
  582. ;
  583. });
  584. gulp.task('package compressed rtl css', false, function () {
  585. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).rtl.css')
  586. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  587. .pipe(concatCSS('semantic.rtl.min.css'))
  588. .pipe(minifyCSS(settings.minify))
  589. .pipe(header(banner, settings.header))
  590. .pipe(gulp.dest(output.packaged))
  591. .pipe(print(log.created))
  592. ;
  593. });
  594. /*--------------
  595. Internal
  596. ---------------*/
  597. gulp.task('package uncompressed css', false, function() {
  598. return gulp.src(output.uncompressed + '**/' + componentGlob + config.ignoredFiles + '.css')
  599. .pipe(plumber())
  600. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  601. .pipe(concatCSS('semantic.css'))
  602. .pipe(chmod(config.permission))
  603. .pipe(gulp.dest(output.packaged))
  604. .pipe(print(log.created))
  605. ;
  606. });
  607. gulp.task('package compressed css', false, function() {
  608. return gulp.src(output.uncompressed + '**/' + componentGlob + config.ignoredFiles + '.css')
  609. .pipe(plumber())
  610. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  611. .pipe(concatCSS('semantic.min.css'))
  612. .pipe(minifyCSS(settings.minify))
  613. .pipe(header(banner, settings.header))
  614. .pipe(chmod(config.permission))
  615. .pipe(gulp.dest(output.packaged))
  616. .pipe(print(log.created))
  617. ;
  618. });
  619. gulp.task('package uncompressed js', false, function() {
  620. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).js')
  621. .pipe(plumber())
  622. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  623. .pipe(concat('semantic.js'))
  624. .pipe(header(banner, settings.header))
  625. .pipe(chmod(config.permission))
  626. .pipe(gulp.dest(output.packaged))
  627. .pipe(print(log.created))
  628. ;
  629. });
  630. gulp.task('package compressed js', false, function() {
  631. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).js')
  632. .pipe(plumber())
  633. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  634. .pipe(concat('semantic.min.js'))
  635. .pipe(uglify(settings.uglify))
  636. .pipe(header(banner, settings.header))
  637. .pipe(chmod(config.permission))
  638. .pipe(gulp.dest(output.packaged))
  639. .pipe(print(log.created))
  640. ;
  641. });
  642. /*******************************
  643. Install Tasks
  644. *******************************/
  645. var
  646. // install dependencies
  647. jeditor = require('gulp-json-editor'),
  648. prompt = require('gulp-prompt'),
  649. wrench = require('wrench'),
  650. questions = require('./tasks/questions'),
  651. ;
  652. gulp.task('check install', false, function () {
  653. setTimeout(function() {
  654. if( runSetup || !fs.existsSync(config.files.site)) {
  655. console.log('No semantic.json file found. Starting install...');
  656. gulp.start('install');
  657. }
  658. else {
  659. gulp.start('watch');
  660. }
  661. }, 50);
  662. });
  663. gulp.task('install', 'Set-up project for first time', function () {
  664. console.clear();
  665. gulp
  666. .src('gulpfile.js')
  667. .pipe(prompt.prompt(questions.setup, function(answers) {
  668. var
  669. siteVariable = /@siteFolder .*\'(.*)/mg,
  670. siteDestination = answers.site || config.folders.site,
  671. pathToSite = path.relative(path.resolve(config.folders.theme), path.resolve(siteDestination)).replace(/\\/g,'/'),
  672. sitePathReplace = "@siteFolder : '" + pathToSite + "/';",
  673. configExists = fs.existsSync(config.files.config),
  674. themeConfigExists = fs.existsSync(config.files.theme),
  675. siteExists = fs.existsSync(siteDestination),
  676. jsonSource = (configExists)
  677. ? config.files.config
  678. : config.templates.config,
  679. json = {
  680. paths: {
  681. source: {},
  682. output: {}
  683. }
  684. }
  685. ;
  686. // exit if config exists and user specifies no overwrite
  687. if(answers.overwrite !== undefined && answers.overwrite == 'no') {
  688. return;
  689. }
  690. console.clear();
  691. console.log('Installing');
  692. console.log('------------------------------');
  693. // create site files
  694. if(siteExists) {
  695. console.info('Site folder exists, merging files (no overwrite)', siteDestination);
  696. }
  697. else {
  698. console.info('Creating site theme folder', siteDestination);
  699. }
  700. // copy recursively without overwrite
  701. wrench.copyDirSyncRecursive(config.templates.site, siteDestination, settings.wrench.recursive);
  702. // adjust less variable for site folder location
  703. console.info('Adjusting @siteFolder', sitePathReplace);
  704. if(themeConfigExists) {
  705. gulp.src(config.files.site)
  706. .pipe(plumber())
  707. .pipe(replace(siteVariable, sitePathReplace))
  708. .pipe(chmod(config.permission))
  709. .pipe(gulp.dest(config.folders.theme))
  710. ;
  711. }
  712. else {
  713. console.info('Creating src/theme.config (LESS config)');
  714. gulp.src(config.templates.theme)
  715. .pipe(plumber())
  716. .pipe(rename({ extname : '' }))
  717. .pipe(replace(siteVariable, sitePathReplace))
  718. .pipe(chmod(config.permission))
  719. .pipe(gulp.dest(config.folders.theme))
  720. ;
  721. }
  722. // determine semantic.json config
  723. if(answers.components) {
  724. json.components = answers.components;
  725. }
  726. if(answers.permission) {
  727. json.permission = +answers.permission;
  728. }
  729. if(answers.dist) {
  730. answers.dist = answers.dist;
  731. json.paths.output = {
  732. packaged : answers.dist + '/',
  733. uncompressed : answers.dist + '/components/',
  734. compressed : answers.dist + '/components/',
  735. themes : answers.dist + '/themes/'
  736. };
  737. }
  738. if(answers.rtl) {
  739. json.rtl = (answers.rtl == 'yes')
  740. ? true
  741. : false
  742. ;
  743. }
  744. if(answers.site) {
  745. json.paths.source.site = answers.site + '/';
  746. }
  747. if(answers.packaged) {
  748. json.paths.output.packaged = answers.packaged + '/';
  749. }
  750. if(answers.compressed) {
  751. json.paths.output.compressed = answers.compressed + '/';
  752. }
  753. if(answers.uncompressed) {
  754. json.paths.output.uncompressed = answers.uncompressed + '/';
  755. }
  756. // write semantic.json
  757. if(configExists) {
  758. console.info('Extending semantic.json (Gulp config)');
  759. gulp.src(jsonSource)
  760. .pipe(plumber())
  761. .pipe(rename(settings.rename.json)) // preserve file extension
  762. .pipe(jeditor(json))
  763. .pipe(chmod(config.permission))
  764. .pipe(gulp.dest('./'))
  765. ;
  766. }
  767. else {
  768. console.info('Creating semantic.json (Gulp config)');
  769. gulp.src(jsonSource)
  770. .pipe(plumber())
  771. .pipe(rename({ extname : '' })) // remove .template from ext
  772. .pipe(jeditor(json))
  773. .pipe(chmod(config.permission))
  774. .pipe(gulp.dest('./'))
  775. ;
  776. }
  777. console.log('');
  778. console.log('');
  779. }))
  780. .pipe(prompt.prompt(questions.cleanup, function(answers) {
  781. if(answers.cleanup == 'yes') {
  782. del(config.setupFiles);
  783. }
  784. if(answers.build == 'yes') {
  785. config = require(config.files.config);
  786. getConfigValues();
  787. gulp.start('build');
  788. }
  789. }))
  790. ;
  791. });
  792. /*******************************
  793. Admin Tasks
  794. *******************************/
  795. var
  796. // admin dependencies
  797. concatFileNames = require('gulp-concat-filenames'),
  798. git = require('gulp-git'),
  799. githubAPI = require('github'),
  800. runSequence = require('run-sequence'),
  801. tap = require('gulp-tap'),
  802. // admin files
  803. adminQuestions = require('./tasks/admin/questions'),
  804. release = require('./tasks/admin/release'),
  805. // stores oauth info for GitHub API
  806. oAuth = fs.existsSync('./tasks/admin/oauth.js')
  807. ? require('./tasks/admin/oauth')
  808. : false,
  809. github,
  810. ;
  811. /*--------------
  812. Docs
  813. ---------------*/
  814. /* Moves watched files to static site generator output */
  815. gulp.task('serve-docs', false, function () {
  816. config = require('./tasks/admin/docs.json');
  817. getConfigValues();
  818. // copy source files
  819. gulp
  820. .watch([
  821. 'src/**/*.*'
  822. ], function(file) {
  823. console.clear();
  824. return gulp.src(file.path, { base: 'src/' })
  825. .pipe(chmod(config.permission))
  826. .pipe(gulp.dest(output.less))
  827. .pipe(print(log.created))
  828. ;
  829. })
  830. ;
  831. gulp.start('watch');
  832. });
  833. /* Builds files to docs source */
  834. gulp.task('build-docs', false, function () {
  835. console.clear();
  836. // pushes to docpad files
  837. config = require('./tasks/admin/docs.json');
  838. getConfigValues();
  839. gulp.start('build');
  840. // copy source
  841. gulp.src('src/**/*.*')
  842. .pipe(chmod(config.permission))
  843. .pipe(gulp.dest(output.less))
  844. .pipe(print(log.created))
  845. ;
  846. });
  847. /* Release */
  848. gulp.task('release', false, function() {
  849. // gulp build
  850. runSequence(
  851. 'build',
  852. 'create files'
  853. );
  854. });
  855. /* Release All */
  856. gulp.task('release all', false, function() {
  857. if(!oAuth) {
  858. console.error('Must add node include tasks/admin/oauth.js with oauth token for GitHub');
  859. return;
  860. }
  861. github = new githubAPI({
  862. version : '3.0.0',
  863. debug : true,
  864. protocol : 'https',
  865. timeout : 5000
  866. });
  867. github.authenticate({
  868. type: 'oauth',
  869. token: oAuth.token
  870. });
  871. // gulp build
  872. runSequence(
  873. 'build',
  874. 'create components',
  875. 'update component repos'
  876. );
  877. });
  878. /*--------------
  879. Internal
  880. ---------------*/
  881. /*
  882. This will create individual component repositories for each SUI component
  883. * copy component files from release
  884. * create commonjs files as index.js for NPM release
  885. * create release notes that filter only items related to component
  886. * custom package.json file from template
  887. * create bower.json from template
  888. * create README from template
  889. * create meteor.js file
  890. */
  891. gulp.task('create components', false, function(callback) {
  892. var
  893. stream,
  894. index,
  895. tasks = []
  896. ;
  897. for(index in release.components) {
  898. var
  899. component = release.components[index]
  900. ;
  901. // streams... designed to save time and make coding fun...
  902. (function(component) {
  903. var
  904. outputDirectory = release.outputRoot + component,
  905. isJavascript = fs.existsSync(output.compressed + component + '.js'),
  906. isCSS = fs.existsSync(output.compressed + component + '.css'),
  907. capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1),
  908. packageName = release.packageRoot + component,
  909. repoName = release.repoRoot + capitalizedComponent,
  910. gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git',
  911. repoURL = 'https://github.com/' + release.org + '/' + repoName + '/',
  912. regExp = {
  913. match : {
  914. // templated values
  915. name : '{component}',
  916. titleName : '{Component}',
  917. version : '{version}',
  918. files : '{files}',
  919. // release notes
  920. spacedVersions : /(###.*\n)\n+(?=###)/gm,
  921. spacedLists : /(^- .*\n)\n+(?=^-)/gm,
  922. trim : /^\s+|\s+$/g,
  923. unrelatedNotes : new RegExp('^((?!(^.*(' + component + ').*$|###.*)).)*$', 'gmi'),
  924. whitespace : /\n\s*\n\s*\n/gm,
  925. // npm
  926. export : /\$\.fn\.\w+\s*=\s*function\(parameters\)\s*{/g,
  927. formExport : /\$\.fn\.\w+\s*=\s*function\(fields, parameters\)\s*{/g,
  928. settingsExport : /\$\.fn\.\w+\.settings\s*=/g,
  929. settingsReference : /\$\.fn\.\w+\.settings/g,
  930. jQuery : /jQuery/g,
  931. },
  932. replace : {
  933. // readme
  934. name : component,
  935. titleName : capitalizedComponent,
  936. // release notes
  937. spacedVersions : '',
  938. spacedLists : '$1',
  939. trim : '',
  940. unrelatedNotes : '',
  941. whitespace : '\n\n',
  942. // npm
  943. export : 'module.exports = function(parameters) {\n var _module = module;\n',
  944. formExport : 'module.exports = function(fields, parameters) {\n var _module = module;\n',
  945. settingsExport : 'module.exports.settings =',
  946. settingsReference : '_module.exports.settings',
  947. jQuery : 'require("jquery")'
  948. }
  949. },
  950. task = {
  951. all : component + ' creating',
  952. repo : component + ' create repo',
  953. bower : component + ' create bower.json',
  954. readme : component + ' create README',
  955. npm : component + ' create NPM Module',
  956. notes : component + ' create release notes',
  957. composer : component + ' create composer.json',
  958. package : component + ' create package.json',
  959. meteor : component + ' create package.js',
  960. }
  961. ;
  962. // copy dist files into output folder adjusting asset paths
  963. gulp.task(task.repo, false, function() {
  964. return gulp.src(release.source + component + '.*')
  965. .pipe(plumber())
  966. .pipe(flatten())
  967. .pipe(replace(release.paths.source, release.paths.output))
  968. .pipe(chmod(config.permission))
  969. .pipe(gulp.dest(outputDirectory))
  970. ;
  971. });
  972. // create npm module
  973. gulp.task(task.npm, false, function() {
  974. return gulp.src(release.source + component + '!(*.min|*.map).js')
  975. .pipe(plumber())
  976. .pipe(flatten())
  977. .pipe(replace(regExp.match.export, regExp.replace.export))
  978. .pipe(replace(regExp.match.formExport, regExp.replace.formExport))
  979. .pipe(replace(regExp.match.settingsExport, regExp.replace.settingsExport))
  980. .pipe(replace(regExp.match.settingsReference, regExp.replace.settingsReference))
  981. .pipe(replace(regExp.match.jQuery, regExp.replace.jQuery))
  982. .pipe(rename('index.js'))
  983. .pipe(chmod(config.permission))
  984. .pipe(gulp.dest(outputDirectory))
  985. ;
  986. });
  987. // create readme
  988. gulp.task(task.readme, false, function() {
  989. return gulp.src(release.templates.readme)
  990. .pipe(plumber())
  991. .pipe(flatten())
  992. .pipe(replace(regExp.match.name, regExp.replace.name))
  993. .pipe(replace(regExp.match.titleName, regExp.replace.titleName))
  994. .pipe(chmod(config.permission))
  995. .pipe(gulp.dest(outputDirectory))
  996. ;
  997. });
  998. // extend bower.json
  999. gulp.task(task.bower, false, function() {
  1000. return gulp.src(release.templates.bower)
  1001. .pipe(plumber())
  1002. .pipe(flatten())
  1003. .pipe(jeditor(function(bower) {
  1004. bower.name = packageName;
  1005. bower.description = capitalizedComponent + ' - Semantic UI';
  1006. if(isJavascript) {
  1007. if(isCSS) {
  1008. bower.main = [
  1009. component + '.js',
  1010. component + '.css'
  1011. ];
  1012. }
  1013. else {
  1014. bower.main = [
  1015. component + '.js'
  1016. ];
  1017. }
  1018. bower.dependencies = {
  1019. jquery: '>=1.8'
  1020. };
  1021. }
  1022. else {
  1023. bower.main = [
  1024. component + '.css'
  1025. ];
  1026. }
  1027. return bower;
  1028. }))
  1029. .pipe(chmod(config.permission))
  1030. .pipe(gulp.dest(outputDirectory))
  1031. ;
  1032. });
  1033. // extend package.json
  1034. gulp.task(task.package, false, function() {
  1035. return gulp.src(release.templates.package)
  1036. .pipe(plumber())
  1037. .pipe(flatten())
  1038. .pipe(jeditor(function(package) {
  1039. if(isJavascript) {
  1040. package.dependencies = {
  1041. jquery: 'x.x.x'
  1042. };
  1043. package.main = 'index.js';
  1044. }
  1045. package.name = packageName;
  1046. if(version) {
  1047. package.version = version;
  1048. }
  1049. package.title = 'Semantic UI - ' + capitalizedComponent;
  1050. package.description = 'Single component release of ' + component;
  1051. package.repository = {
  1052. type : 'git',
  1053. url : gitURL
  1054. };
  1055. return package;
  1056. }))
  1057. .pipe(chmod(config.permission))
  1058. .pipe(gulp.dest(outputDirectory))
  1059. ;
  1060. });
  1061. // extend composer.json
  1062. gulp.task(task.composer, false, function() {
  1063. return gulp.src(release.templates.composer)
  1064. .pipe(plumber())
  1065. .pipe(flatten())
  1066. .pipe(jeditor(function(composer) {
  1067. if(isJavascript) {
  1068. composer.dependencies = {
  1069. jquery: 'x.x.x'
  1070. };
  1071. composer.main = component + '.js';
  1072. }
  1073. composer.name = 'semantic/' + component;
  1074. if(version) {
  1075. composer.version = version;
  1076. }
  1077. composer.description = 'Single component release of ' + component;
  1078. return composer;
  1079. }))
  1080. .pipe(chmod(config.permission))
  1081. .pipe(gulp.dest(outputDirectory))
  1082. ;
  1083. });
  1084. // create release notes
  1085. gulp.task(task.notes, false, function() {
  1086. return gulp.src(release.templates.notes)
  1087. .pipe(plumber())
  1088. .pipe(flatten())
  1089. // Remove release notes for lines not mentioning component
  1090. .pipe(replace(regExp.match.unrelatedNotes, regExp.replace.unrelatedNotes))
  1091. .pipe(replace(regExp.match.whitespace, regExp.replace.whitespace))
  1092. .pipe(replace(regExp.match.spacedVersions, regExp.replace.spacedVersions))
  1093. .pipe(replace(regExp.match.spacedLists, regExp.replace.spacedLists))
  1094. .pipe(replace(regExp.match.trim, regExp.replace.trim))
  1095. .pipe(chmod(config.permission))
  1096. .pipe(gulp.dest(outputDirectory))
  1097. ;
  1098. });
  1099. // Creates component meteor package.js
  1100. gulp.task(task.meteor, function() {
  1101. var
  1102. fileNames = ''
  1103. ;
  1104. if(isJavascript) {
  1105. fileNames += ' \'' + component + '.js\',\n';
  1106. }
  1107. if(isCSS) {
  1108. fileNames += ' \'' + component + '.css\',\n';
  1109. }
  1110. return gulp.src(outputDirectory + '/assets/**/' + component + '?(s).*', { base: outputDirectory})
  1111. .pipe(concatFileNames('dummy.txt', {
  1112. newline : '',
  1113. root : outputDirectory,
  1114. prepend : ' \'',
  1115. append : '\','
  1116. }))
  1117. .pipe(tap(function(file) { fileNames += file.contents;}))
  1118. .on('end', function(){
  1119. gulp.src(release.templates.meteorComponent)
  1120. .pipe(plumber())
  1121. .pipe(flatten())
  1122. .pipe(replace(regExp.match.name, regExp.replace.name))
  1123. .pipe(replace(regExp.match.titleName, regExp.replace.titleName))
  1124. .pipe(replace(regExp.match.version, version))
  1125. .pipe(replace(regExp.match.files, fileNames))
  1126. .pipe(rename(defaults.files.npm))
  1127. .pipe(gulp.dest(outputDirectory))
  1128. ;
  1129. })
  1130. ;
  1131. });
  1132. // synchronous tasks in orchestrator? I think not
  1133. gulp.task(task.all, false, function(callback) {
  1134. runSequence([
  1135. task.repo,
  1136. task.npm,
  1137. task.bower,
  1138. task.readme,
  1139. task.package,
  1140. task.composer,
  1141. task.notes,
  1142. task.meteor
  1143. ], callback);
  1144. });
  1145. tasks.push(task.all);
  1146. })(component);
  1147. }
  1148. runSequence(tasks, callback);
  1149. });
  1150. gulp.task('register repos', false, function(callback) {
  1151. var
  1152. index = -1,
  1153. total = release.components.length,
  1154. process = require('child_process'),
  1155. stream,
  1156. stepRepo
  1157. ;
  1158. console.log('Registering repos with package managers');
  1159. // Do Git commands synchronously per component, to avoid issues
  1160. stepRepo = function() {
  1161. index = index + 1;
  1162. if(index >= total) {
  1163. return;
  1164. }
  1165. var
  1166. component = release.components[index],
  1167. outputDirectory = release.outputRoot + component + '/',
  1168. capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1),
  1169. packageName = release.packageRoot + component,
  1170. repoName = release.repoRoot + capitalizedComponent,
  1171. gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git',
  1172. exec = process.exec,
  1173. execSettings = {cwd: outputDirectory},
  1174. registerBower = 'bower register ' + packageName + ' ' + gitURL,
  1175. registerNPM = 'npm publish'
  1176. ;
  1177. /* One time register
  1178. exec(registerBower, execSettings, function(err, stdout, stderr) {
  1179. stepRepo();
  1180. });
  1181. */
  1182. /* Update npm
  1183. exec(registerNPM, execSettings, function(err, stdout, stderr) {
  1184. console.log(err, stdout, stderr);
  1185. stepRepo();
  1186. });
  1187. */
  1188. };
  1189. stepRepo();
  1190. });
  1191. gulp.task('update component repos', false, function() {
  1192. var
  1193. index = -1,
  1194. total = release.components.length,
  1195. stream,
  1196. stepRepo
  1197. ;
  1198. console.log('Handling git');
  1199. // Do Git commands synchronously per component, to avoid issues
  1200. stepRepo = function() {
  1201. index = index + 1;
  1202. if(index >= total) {
  1203. return;
  1204. }
  1205. var
  1206. component = release.components[index],
  1207. outputDirectory = release.outputRoot + component + '/',
  1208. capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1),
  1209. repoName = release.repoRoot + capitalizedComponent,
  1210. gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git',
  1211. repoURL = 'https://github.com/' + release.org + '/' + repoName + '/',
  1212. gitOptions = { cwd: outputDirectory },
  1213. quietOptions = { args: '-q', cwd: outputDirectory },
  1214. isRepository = fs.existsSync(outputDirectory + '.git/'),
  1215. componentPackage = fs.existsSync(outputDirectory + 'package.json' )
  1216. ? require(outputDirectory + 'package.json')
  1217. : false,
  1218. commitArgs = (oAuth.name !== undefined && oAuth.email !== undefined)
  1219. ? '--author "' + oAuth.name + ' <' + oAuth.email + '>"'
  1220. : '',
  1221. isNewVersion = (version && componentPackage.version != version),
  1222. mergeMessage = 'Merged from upstream',
  1223. commitMessage = (isNewVersion)
  1224. ? 'Updated component to version ' + version
  1225. : 'Updated component release from Semantic-UI (Automatic)'
  1226. ;
  1227. console.log('Processing repository:' + outputDirectory);
  1228. if(isRepository) {
  1229. commitFiles();
  1230. }
  1231. else {
  1232. createRepo();
  1233. }
  1234. // standard path
  1235. function commitFiles() {
  1236. // commit files
  1237. console.log('Committing files', commitArgs);
  1238. gulp.src('**/*', gitOptions)
  1239. .pipe(git.add(gitOptions))
  1240. .pipe(git.commit(commitMessage, { args: commitArgs, cwd: outputDirectory }))
  1241. .on('error', function(error) {
  1242. console.log('Nothing new to commit');
  1243. stepRepo();
  1244. })
  1245. .on('finish', function(callback) {
  1246. pullFiles();
  1247. })
  1248. ;
  1249. }
  1250. function pullFiles() {
  1251. console.log('Pulling files');
  1252. git.pull('origin', 'master', { args: '', cwd: outputDirectory }, function(error) {
  1253. if(error && error.message.search("Couldn't find remote ref") != -1) {
  1254. createRepo();
  1255. }
  1256. else {
  1257. console.log('Pull completed successfully');
  1258. mergeCommit();
  1259. }
  1260. });
  1261. }
  1262. function mergeCommit() {
  1263. // commit files
  1264. console.log('Adding merge commit', commitArgs);
  1265. gulp.src('', gitOptions)
  1266. .pipe(git.add(gitOptions))
  1267. .pipe(git.commit(mergeMessage, { args: commitArgs, cwd: outputDirectory }))
  1268. .on('error', function(error) {
  1269. console.log('Nothing new to merge', error);
  1270. })
  1271. .on('finish', function(callback) {
  1272. if(1) {
  1273. tagFiles();
  1274. }
  1275. else {
  1276. pushFiles();
  1277. }
  1278. })
  1279. ;
  1280. }
  1281. function tagFiles() {
  1282. console.log('Tagging new version ', version);
  1283. git.tag(version, 'Updated version from semantic-ui (automatic)', function (err) {
  1284. pushFiles();
  1285. });
  1286. }
  1287. function pushFiles() {
  1288. console.log('Pushing files');
  1289. git.push('origin', 'master', { args: '', cwd: outputDirectory }, function(error) {
  1290. if(error && error.message.search("Couldn't find remote ref") == -1) {
  1291. createRepo();
  1292. }
  1293. console.log('Push completed successfully');
  1294. stepRepo();
  1295. });
  1296. }
  1297. // set-up path
  1298. function createRepo() {
  1299. console.log('Creating repository ' + repoURL);
  1300. github.repos.createFromOrg({
  1301. org : release.org,
  1302. name : repoName,
  1303. homepage : release.homepage
  1304. }, function() {
  1305. if(isRepository) {
  1306. addRemote();
  1307. }
  1308. else {
  1309. initRepo();
  1310. }
  1311. });
  1312. }
  1313. function initRepo() {
  1314. console.log('Initializing repository in ' + outputDirectory);
  1315. git.init(gitOptions, function(error) {
  1316. if(error) {
  1317. console.error('Error initializing repo');
  1318. return;
  1319. }
  1320. addRemote();
  1321. });
  1322. }
  1323. function addRemote() {
  1324. console.log('Adding remote origin as ' + gitURL);
  1325. git.addRemote('origin', gitURL, gitOptions, firstPushFiles);
  1326. }
  1327. function firstPushFiles() {
  1328. console.log('Pushing files');
  1329. git.push('origin', 'master', { args: '-u', cwd: outputDirectory }, function(error) {
  1330. if(error) {
  1331. console.log(error);
  1332. pullFiles();
  1333. }
  1334. else {
  1335. console.log('First push completed successfully');
  1336. stepRepo();
  1337. }
  1338. });
  1339. }
  1340. };
  1341. return stepRepo();
  1342. });