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.

633 lines
17 KiB

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
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. All configurable options are defined inside build.config
  3. Please adjust this to your site's settings
  4. */
  5. /*******************************
  6. Set-up
  7. *******************************/
  8. var
  9. gulp = require('gulp-help')(require('gulp')),
  10. // node components & oddballs
  11. del = require('del'),
  12. fs = require('fs'),
  13. extend = require('extend'),
  14. path = require('path'),
  15. console = require('better-console'),
  16. wrench = require('wrench'),
  17. // gulp dependencies
  18. autoprefixer = require('gulp-autoprefixer'),
  19. clone = require('gulp-clone'),
  20. concat = require('gulp-concat'),
  21. concatCSS = require('gulp-concat-css'),
  22. copy = require('gulp-copy'),
  23. debug = require('gulp-debug'),
  24. flatten = require('gulp-flatten'),
  25. header = require('gulp-header'),
  26. jeditor = require('gulp-json-editor'),
  27. karma = require('gulp-karma'),
  28. less = require('gulp-less'),
  29. minifyCSS = require('gulp-minify-css'),
  30. notify = require('gulp-notify'),
  31. plumber = require('gulp-plumber'),
  32. print = require('gulp-print'),
  33. prompt = require('gulp-prompt'),
  34. rename = require('gulp-rename'),
  35. replace = require('gulp-replace'),
  36. sourcemaps = require('gulp-sourcemaps'),
  37. uglify = require('gulp-uglify'),
  38. util = require('gulp-util'),
  39. watch = require('gulp-watch'),
  40. // config
  41. banner = require('./tasks/banner'),
  42. comments = require('./tasks/comments'),
  43. defaults = require('./tasks/defaults'),
  44. log = require('./tasks/log'),
  45. questions = require('./tasks/questions'),
  46. settings = require('./tasks/gulp-settings'),
  47. // local
  48. runSetup = false,
  49. overwrite = true,
  50. config,
  51. package,
  52. // derived
  53. base,
  54. clean,
  55. output,
  56. source,
  57. assetPaths,
  58. componentGlob,
  59. // temporary
  60. folder
  61. ;
  62. /*******************************
  63. Read Settings
  64. *******************************/
  65. try {
  66. // try to load json
  67. var
  68. config = require(defaults.files.config),
  69. package = require(defaults.files.npm)
  70. ;
  71. }
  72. catch(error) {
  73. var config = false;
  74. }
  75. /*******************************
  76. Values Derived From Config
  77. *******************************/
  78. var
  79. getConfigValues = function() {
  80. if(!config) {
  81. runSetup = true;
  82. config = defaults;
  83. }
  84. config = extend(true, {}, defaults, config);
  85. // shorthand
  86. base = config.base;
  87. clean = config.paths.clean;
  88. output = config.paths.output;
  89. source = config.paths.source;
  90. // create glob for matching filenames from selected components
  91. componentGlob = (typeof config.components == 'object')
  92. ? (config.components.length > 1)
  93. ? '{' + config.components.join(',') + '}'
  94. : config.components[0]
  95. : ''
  96. ;
  97. // relative paths
  98. assetPaths = {
  99. uncompressed : path.relative(output.uncompressed, output.themes),
  100. compressed : path.relative(output.compressed, output.themes),
  101. packaged : path.relative(output.packaged, output.themes)
  102. };
  103. // add base to values
  104. for(var folder in source) {
  105. if(source.hasOwnProperty(folder)) {
  106. source[folder] = base + source[folder];
  107. }
  108. }
  109. for(folder in output) {
  110. if(output.hasOwnProperty(folder)) {
  111. output[folder] = base + output[folder];
  112. }
  113. }
  114. clean = base + clean;
  115. }
  116. ;
  117. getConfigValues();
  118. /*******************************
  119. Tasks
  120. *******************************/
  121. gulp.task('default', false, [
  122. 'check install'
  123. ]);
  124. gulp.task('watch', 'Watch for site/theme changes (Default Task)', function () {
  125. console.clear();
  126. console.log('Watching source files');
  127. if(!fs.existsSync(config.files.theme)) {
  128. console.error('Cant compile LESS. Run "grunt install" to create a theme config file');
  129. return;
  130. }
  131. // watching changes in style
  132. gulp
  133. .watch([
  134. source.config,
  135. source.definitions + '**/*.less',
  136. source.site + '**/*.{overrides,variables}',
  137. source.themes + '**/*.{overrides,variables}'
  138. ], function(file) {
  139. var
  140. srcPath,
  141. stream,
  142. compressedStream,
  143. uncompressedStream
  144. ;
  145. gulp.src(file.path)
  146. .pipe(print(log.modified))
  147. ;
  148. // recompile only definition file
  149. srcPath = util.replaceExtension(file.path, '.less');
  150. srcPath = srcPath.replace(config.regExp.themePath, source.definitions);
  151. srcPath = srcPath.replace(source.site, source.definitions);
  152. // get relative asset path (path returns wrong path? hardcoded)
  153. // assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
  154. assetPaths.source = '../../themes';
  155. if( fs.existsSync(srcPath) ) {
  156. // unified css stream
  157. stream = gulp.src(srcPath)
  158. .pipe(plumber())
  159. //.pipe(sourcemaps.init())
  160. .pipe(less(settings.less))
  161. .pipe(replace(comments.variables.in, comments.variables.out))
  162. .pipe(replace(comments.large.in, comments.large.out))
  163. .pipe(replace(comments.small.in, comments.small.out))
  164. .pipe(replace(comments.tiny.in, comments.tiny.out))
  165. .pipe(autoprefixer(settings.prefix))
  166. ;
  167. // use 2 concurrent streams from same source
  168. uncompressedStream = stream.pipe(clone());
  169. compressedStream = stream.pipe(clone());
  170. uncompressedStream
  171. .pipe(replace(assetPaths.source, assetPaths.uncompressed))
  172. //.pipe(sourcemaps.write('/', settings.sourcemap))
  173. .pipe(header(banner, settings.header))
  174. .pipe(gulp.dest(output.uncompressed))
  175. .pipe(print(log.created))
  176. .on('end', function() {
  177. gulp.start('package uncompressed css');
  178. })
  179. ;
  180. compressedStream = stream
  181. .pipe(clone())
  182. .pipe(replace(assetPaths.source, assetPaths.compressed))
  183. .pipe(minifyCSS(settings.minify))
  184. .pipe(rename(settings.rename.minCSS))
  185. //.pipe(sourcemaps.write('/', settings.sourcemap))
  186. .pipe(header(banner, settings.header))
  187. .pipe(gulp.dest(output.compressed))
  188. .pipe(print(log.created))
  189. .on('end', function() {
  190. gulp.start('package compressed css');
  191. })
  192. ;
  193. }
  194. })
  195. ;
  196. // watch changes in assets
  197. gulp
  198. .watch([
  199. source.themes + '**/assets/**'
  200. ], function(file) {
  201. // copy assets
  202. gulp.src(file.path, { base: source.themes })
  203. .pipe(gulp.dest(output.themes))
  204. .pipe(print(log.created))
  205. ;
  206. })
  207. ;
  208. // watch changes in js
  209. gulp
  210. .watch([
  211. source.definitions + '**/*.js'
  212. ], function(file) {
  213. gulp.src(file.path)
  214. .pipe(gulp.dest(output.uncompressed))
  215. .pipe(print(log.created))
  216. .pipe(sourcemaps.init())
  217. .pipe(uglify(settings.uglify))
  218. .pipe(rename(settings.rename.minJS))
  219. .pipe(gulp.dest(output.compressed))
  220. .pipe(print(log.created))
  221. .on('end', function() {
  222. gulp.start('package compressed js');
  223. gulp.start('package uncompressed js');
  224. })
  225. ;
  226. })
  227. ;
  228. });
  229. // Builds all files
  230. gulp.task('build', 'Builds all files from source', function(callback) {
  231. var
  232. stream,
  233. compressedStream,
  234. uncompressedStream
  235. ;
  236. console.info('Building Semantic');
  237. if(!fs.existsSync(config.files.theme)) {
  238. console.error('Cant build LESS. Run "grunt install" to create a theme config file');
  239. return;
  240. }
  241. // get relative asset path (path returns wrong path?)
  242. // assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
  243. assetPaths.source = '../../themes'; // hardcoded
  244. // copy assets
  245. gulp.src(source.themes + '**/assets/**')
  246. .pipe(gulp.dest(output.themes))
  247. ;
  248. // javascript stream
  249. gulp.src(source.definitions + '**/*.js')
  250. .pipe(flatten())
  251. .pipe(gulp.dest(output.uncompressed))
  252. .pipe(print(log.created))
  253. // .pipe(sourcemaps.init())
  254. .pipe(uglify(settings.uglify))
  255. .pipe(rename(settings.rename.minJS))
  256. .pipe(header(banner, settings.header))
  257. .pipe(gulp.dest(output.compressed))
  258. .pipe(print(log.created))
  259. .on('end', function() {
  260. gulp.start('package compressed js');
  261. gulp.start('package uncompressed js');
  262. })
  263. ;
  264. // unified css stream
  265. stream = gulp.src(source.definitions + '**/*.less')
  266. .pipe(plumber())
  267. //.pipe(sourcemaps.init())
  268. .pipe(less(settings.less))
  269. .pipe(flatten())
  270. .pipe(replace(comments.variables.in, comments.variables.out))
  271. .pipe(replace(comments.large.in, comments.large.out))
  272. .pipe(replace(comments.small.in, comments.small.out))
  273. .pipe(replace(comments.tiny.in, comments.tiny.out))
  274. .pipe(autoprefixer(settings.prefix))
  275. ;
  276. // use 2 concurrent streams from same source
  277. uncompressedStream = stream.pipe(clone());
  278. compressedStream = stream.pipe(clone());
  279. uncompressedStream
  280. .pipe(replace(assetPaths.source, assetPaths.uncompressed))
  281. //.pipe(sourcemaps.write('/', settings.sourcemap))
  282. .pipe(header(banner, settings.header))
  283. .pipe(gulp.dest(output.uncompressed))
  284. .pipe(print(log.created))
  285. .on('end', function() {
  286. gulp.start('package uncompressed css');
  287. })
  288. ;
  289. compressedStream = stream
  290. .pipe(clone())
  291. .pipe(replace(assetPaths.source, assetPaths.compressed))
  292. .pipe(minifyCSS(settings.minify))
  293. .pipe(rename(settings.rename.minCSS))
  294. //.pipe(sourcemaps.write('/', settings.sourcemap))
  295. .pipe(header(banner, settings.header))
  296. .pipe(gulp.dest(output.compressed))
  297. .pipe(print(log.created))
  298. .on('end', function() {
  299. gulp.start('package compressed css');
  300. })
  301. ;
  302. });
  303. // cleans distribution files
  304. gulp.task('clean', 'Clean dist folder', function(callback) {
  305. return del([clean], settings.del, callback);
  306. });
  307. gulp.task('version', 'Displays current version of Semantic', function(callback) {
  308. console.log('Semantic UI ' + package.version);
  309. });
  310. /*--------------
  311. Internal
  312. ---------------*/
  313. gulp.task('package uncompressed css', false, function() {
  314. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).css')
  315. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  316. .pipe(concatCSS('semantic.css'))
  317. .pipe(gulp.dest(output.packaged))
  318. .pipe(print(log.created))
  319. ;
  320. });
  321. gulp.task('package compressed css', false, function() {
  322. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).css')
  323. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  324. .pipe(concatCSS('semantic.min.css'))
  325. .pipe(minifyCSS(settings.minify))
  326. .pipe(header(banner, settings.header))
  327. .pipe(gulp.dest(output.packaged))
  328. .pipe(print(log.created))
  329. ;
  330. });
  331. gulp.task('package uncompressed js', false, function() {
  332. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).js')
  333. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  334. .pipe(concat('semantic.js'))
  335. .pipe(header(banner, settings.header))
  336. .pipe(gulp.dest(output.packaged))
  337. .pipe(print(log.created))
  338. ;
  339. });
  340. gulp.task('package compressed js', false, function() {
  341. return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).js')
  342. .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
  343. .pipe(concat('semantic.min.js'))
  344. .pipe(uglify(settings.uglify))
  345. .pipe(header(banner, settings.header))
  346. .pipe(gulp.dest(output.packaged))
  347. .pipe(print(log.created))
  348. ;
  349. });
  350. /*--------------
  351. Config
  352. ---------------*/
  353. gulp.task('check install', false, function () {
  354. setTimeout(function() {
  355. if( runSetup || !fs.existsSync(config.files.site)) {
  356. console.log('No semantic.json file found. Starting install...');
  357. gulp.start('install');
  358. }
  359. else {
  360. gulp.start('watch');
  361. }
  362. }, 50);
  363. });
  364. gulp.task('install', 'Set-up project for first time', function () {
  365. console.clear();
  366. gulp
  367. .src('gulpfile.js')
  368. .pipe(prompt.prompt(questions.setup, function(answers) {
  369. var
  370. siteVariable = /@siteFolder .*\'(.*)/mg,
  371. siteDestination = answers.site || config.folders.site,
  372. pathToSite = path.relative(path.resolve(config.folders.theme), path.resolve(siteDestination)),
  373. sitePathReplace = "@siteFolder : '" + pathToSite + "/';",
  374. configExists = fs.existsSync(config.files.config),
  375. themeConfigExists = fs.existsSync(config.files.theme),
  376. siteExists = fs.existsSync(siteDestination),
  377. jsonSource = (configExists)
  378. ? config.files.config
  379. : config.templates.config,
  380. json = {
  381. paths: {
  382. source: {},
  383. output: {}
  384. }
  385. }
  386. ;
  387. // exit if config exists and user specifies no overwrite
  388. if(answers.overwrite !== undefined && answers.overwrite == 'no') {
  389. return;
  390. }
  391. console.clear();
  392. console.log('Installing');
  393. console.log('------------------------------');
  394. // create site files
  395. if(siteExists) {
  396. console.info('Site folder exists, merging files (no overwrite)', siteDestination);
  397. }
  398. else {
  399. console.info('Creating site theme folder', siteDestination);
  400. }
  401. // copy recursively without overwrite
  402. wrench.copyDirSyncRecursive(config.templates.site, siteDestination, settings.wrench.recursive);
  403. // adjust less variable for site folder location
  404. console.info('Adjusting @siteFolder', sitePathReplace);
  405. if(themeConfigExists) {
  406. gulp.src(config.files.site)
  407. .pipe(replace(siteVariable, sitePathReplace))
  408. .pipe(gulp.dest(config.folders.theme))
  409. ;
  410. }
  411. else {
  412. console.info('Creating src/theme.config (LESS config)');
  413. gulp.src(config.templates.theme)
  414. .pipe(rename({ extname : '' }))
  415. .pipe(replace(siteVariable, sitePathReplace))
  416. .pipe(gulp.dest(config.folders.theme))
  417. ;
  418. }
  419. // determine semantic.json config
  420. if(answers.components) {
  421. json.components = answers.components;
  422. }
  423. if(answers.dist) {
  424. answers.dist = answers.dist;
  425. json.paths.output = {
  426. packaged : answers.dist + '/',
  427. uncompressed : answers.dist + '/components/',
  428. compressed : answers.dist + '/components/',
  429. themes : answers.dist + '/themes/'
  430. };
  431. }
  432. if(answers.site) {
  433. json.paths.source.site = answers.site + '/';
  434. }
  435. if(answers.packaged) {
  436. json.paths.output.packaged = answers.packaged + '/';
  437. }
  438. if(answers.compressed) {
  439. json.paths.output.compressed = answers.compressed + '/';
  440. }
  441. if(answers.uncompressed) {
  442. json.paths.output.uncompressed = answers.uncompressed + '/';
  443. }
  444. // write semantic.json
  445. if(configExists) {
  446. console.info('Extending semantic.json (Gulp config)');
  447. gulp.src(jsonSource)
  448. .pipe(plumber())
  449. .pipe(rename(settings.rename.json))
  450. .pipe(jeditor(json))
  451. .pipe(gulp.dest('./'))
  452. ;
  453. }
  454. else {
  455. console.info('Creating semantic.json (Gulp config)');
  456. gulp.src(jsonSource)
  457. .pipe(plumber())
  458. .pipe(rename({ extname : '' }))
  459. .pipe(jeditor(json))
  460. .pipe(gulp.dest('./'))
  461. ;
  462. }
  463. console.log('');
  464. console.log('');
  465. }))
  466. .pipe(prompt.prompt(questions.cleanup, function(answers) {
  467. if(answers.cleanup == 'yes') {
  468. del(config.setupFiles);
  469. }
  470. if(answers.build == 'yes') {
  471. config = require(config.files.config);
  472. getConfigValues();
  473. gulp.start('build');
  474. }
  475. }))
  476. ;
  477. });
  478. /*******************************
  479. Admin Tasks
  480. *******************************/
  481. var
  482. adminQuestions = require('./tasks/admin/questions')
  483. ;
  484. gulp.task('docs', false, function() {
  485. gulp
  486. .src('gulpfile.js')
  487. .pipe(prompt.prompt(adminQuestions.docs, function(answers) {
  488. }))
  489. ;
  490. });
  491. /* Moves watched files to static site generator output */
  492. gulp.task('serve-docs', false, function () {
  493. config = require('./tasks/admin/docs.json');
  494. getConfigValues();
  495. // copy source files
  496. gulp
  497. .watch([
  498. 'src/**/*.*'
  499. ], function(file) {
  500. console.clear();
  501. return gulp.src(file.path, { base: 'src/' })
  502. .pipe(gulp.dest(output.less))
  503. .pipe(print(log.created))
  504. ;
  505. })
  506. ;
  507. gulp.start('watch');
  508. });
  509. /* Builds files to docs source */
  510. gulp.task('build-docs', false, function () {
  511. console.clear();
  512. // pushes to docpad files
  513. config = require('./tasks/admin/docs.json');
  514. getConfigValues();
  515. gulp.start('build');
  516. // copy source
  517. gulp.src('src/**/*.*')
  518. .pipe(gulp.dest(output.less))
  519. .pipe(print(log.created))
  520. ;
  521. });
  522. /* Bump Version */
  523. gulp.task('bump', false, function () {
  524. // bump package.json
  525. // bump composer.json
  526. });
  527. /* Release */
  528. gulp.task('release', false, function() {
  529. });
  530. gulp.task('release all', false, function () {
  531. // Create SCSS Version
  532. // Create RTL Release
  533. // Create Node Release
  534. // Create Bower Releases
  535. });