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.

332 lines
11 KiB

9 years ago
  1. /*******************************
  2. Create Component Repos
  3. *******************************/
  4. /*
  5. This will create individual component repositories for each SUI component
  6. * copy component files from release
  7. * create commonjs files as index.js for NPM release
  8. * create release notes that filter only items related to component
  9. * custom package.json file from template
  10. * create bower.json from template
  11. * create README from template
  12. * create meteor.js file
  13. */
  14. var
  15. gulp = require('gulp'),
  16. // node dependencies
  17. console = require('better-console'),
  18. del = require('del'),
  19. fs = require('fs'),
  20. path = require('path'),
  21. runSequence = require('run-sequence'),
  22. // admin dependencies
  23. concatFileNames = require('gulp-concat-filenames'),
  24. debug = require('gulp-debug'),
  25. flatten = require('gulp-flatten'),
  26. git = require('gulp-git'),
  27. jsonEditor = require('gulp-json-editor'),
  28. plumber = require('gulp-plumber'),
  29. rename = require('gulp-rename'),
  30. replace = require('gulp-replace'),
  31. tap = require('gulp-tap'),
  32. util = require('gulp-util'),
  33. // config
  34. config = require('../../config/user'),
  35. release = require('../../config/admin/release'),
  36. project = require('../../config/project/release'),
  37. // shorthand
  38. version = project.version,
  39. output = config.paths.output
  40. ;
  41. module.exports = function(callback) {
  42. var
  43. stream,
  44. index,
  45. tasks = []
  46. ;
  47. for(index in release.components) {
  48. var
  49. component = release.components[index]
  50. ;
  51. // streams... designed to save time and make coding fun...
  52. (function(component) {
  53. var
  54. outputDirectory = path.join(release.outputRoot, component),
  55. isJavascript = fs.existsSync(output.compressed + component + '.js'),
  56. isCSS = fs.existsSync(output.compressed + component + '.css'),
  57. capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1),
  58. packageName = release.packageRoot + component,
  59. repoName = release.componentRepoRoot + capitalizedComponent,
  60. gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git',
  61. repoURL = 'https://github.com/' + release.org + '/' + repoName + '/',
  62. concatSettings = {
  63. newline : '',
  64. root : outputDirectory,
  65. prepend : " '",
  66. append : "',"
  67. },
  68. regExp = {
  69. match : {
  70. // templated values
  71. name : '{component}',
  72. titleName : '{Component}',
  73. version : '{version}',
  74. files : '{files}',
  75. // release notes
  76. spacedVersions : /(###.*\n)\n+(?=###)/gm,
  77. spacedLists : /(^- .*\n)\n+(?=^-)/gm,
  78. trim : /^\s+|\s+$/g,
  79. unrelatedNotes : new RegExp('^((?!(^.*(' + component + ').*$|###.*)).)*$', 'gmi'),
  80. whitespace : /\n\s*\n\s*\n/gm,
  81. // npm
  82. componentExport : /(.*)\$\.fn\.\w+\s*=\s*function\(([^\)]*)\)\s*{/g,
  83. componentReference: '$.fn.' + component,
  84. settingsExport : /\$\.fn\.\w+\.settings\s*=/g,
  85. settingsReference : /\$\.fn\.\w+\.settings/g,
  86. trailingComma : /,(?=[^,]*$)/,
  87. jQuery : /jQuery/g,
  88. },
  89. replace : {
  90. // readme
  91. name : component,
  92. titleName : capitalizedComponent,
  93. // release notes
  94. spacedVersions : '',
  95. spacedLists : '$1',
  96. trim : '',
  97. unrelatedNotes : '',
  98. whitespace : '\n\n',
  99. // npm
  100. componentExport : 'var _module = module;\n$1module.exports = function($2) {',
  101. componentReference: '_module.exports',
  102. settingsExport : 'module.exports.settings =',
  103. settingsReference : '_module.exports.settings',
  104. jQuery : 'require("jquery")'
  105. }
  106. },
  107. task = {
  108. all : component + ' creating',
  109. repo : component + ' create repo',
  110. bower : component + ' create bower.json',
  111. readme : component + ' create README',
  112. npm : component + ' create NPM Module',
  113. notes : component + ' create release notes',
  114. composer : component + ' create composer.json',
  115. package : component + ' create package.json',
  116. meteor : component + ' create meteor package.js',
  117. },
  118. // paths to includable assets
  119. manifest = {
  120. assets : outputDirectory + '/assets/**/' + component + '?(s).*',
  121. component : outputDirectory + '/' + component + '+(.js|.css)'
  122. }
  123. ;
  124. // copy dist files into output folder adjusting asset paths
  125. gulp.task(task.repo, false, function() {
  126. return gulp.src(release.source + component + '.*')
  127. .pipe(plumber())
  128. .pipe(flatten())
  129. .pipe(replace(release.paths.source, release.paths.output))
  130. .pipe(gulp.dest(outputDirectory))
  131. ;
  132. });
  133. // create npm module
  134. gulp.task(task.npm, false, function() {
  135. return gulp.src(release.source + component + '!(*.min|*.map).js')
  136. .pipe(plumber())
  137. .pipe(flatten())
  138. .pipe(replace(regExp.match.componentExport, regExp.replace.componentExport))
  139. .pipe(replace(regExp.match.componentReference, regExp.replace.componentReference))
  140. .pipe(replace(regExp.match.settingsExport, regExp.replace.settingsExport))
  141. .pipe(replace(regExp.match.settingsReference, regExp.replace.settingsReference))
  142. .pipe(replace(regExp.match.jQuery, regExp.replace.jQuery))
  143. .pipe(rename('index.js'))
  144. .pipe(gulp.dest(outputDirectory))
  145. ;
  146. });
  147. // create readme
  148. gulp.task(task.readme, false, function() {
  149. return gulp.src(release.templates.readme)
  150. .pipe(plumber())
  151. .pipe(flatten())
  152. .pipe(replace(regExp.match.name, regExp.replace.name))
  153. .pipe(replace(regExp.match.titleName, regExp.replace.titleName))
  154. .pipe(gulp.dest(outputDirectory))
  155. ;
  156. });
  157. // extend bower.json
  158. gulp.task(task.bower, false, function() {
  159. return gulp.src(release.templates.bower)
  160. .pipe(plumber())
  161. .pipe(flatten())
  162. .pipe(jsonEditor(function(bower) {
  163. bower.name = packageName;
  164. bower.description = capitalizedComponent + ' - Semantic UI';
  165. if(isJavascript) {
  166. if(isCSS) {
  167. bower.main = [
  168. component + '.js',
  169. component + '.css'
  170. ];
  171. }
  172. else {
  173. bower.main = [
  174. component + '.js'
  175. ];
  176. }
  177. bower.dependencies = {
  178. jquery: '>=1.8'
  179. };
  180. }
  181. else {
  182. bower.main = [
  183. component + '.css'
  184. ];
  185. }
  186. return bower;
  187. }))
  188. .pipe(gulp.dest(outputDirectory))
  189. ;
  190. });
  191. // extend package.json
  192. gulp.task(task.package, false, function() {
  193. return gulp.src(release.templates.package)
  194. .pipe(plumber())
  195. .pipe(flatten())
  196. .pipe(jsonEditor(function(npm) {
  197. if(isJavascript) {
  198. npm.dependencies = {
  199. jquery: 'x.x.x'
  200. };
  201. npm.main = 'index.js';
  202. }
  203. npm.name = packageName;
  204. if(version) {
  205. npm.version = version;
  206. }
  207. npm.title = 'Semantic UI - ' + capitalizedComponent;
  208. npm.description = 'Single component release of ' + component;
  209. npm.repository = {
  210. type : 'git',
  211. url : gitURL
  212. };
  213. return npm;
  214. }))
  215. .pipe(gulp.dest(outputDirectory))
  216. ;
  217. });
  218. // extend composer.json
  219. gulp.task(task.composer, false, function() {
  220. return gulp.src(release.templates.composer)
  221. .pipe(plumber())
  222. .pipe(flatten())
  223. .pipe(jsonEditor(function(composer) {
  224. if(isJavascript) {
  225. composer.dependencies = {
  226. jquery: 'x.x.x'
  227. };
  228. composer.main = component + '.js';
  229. }
  230. composer.name = 'semantic/' + component;
  231. if(version) {
  232. composer.version = version;
  233. }
  234. composer.description = 'Single component release of ' + component;
  235. return composer;
  236. }))
  237. .pipe(gulp.dest(outputDirectory))
  238. ;
  239. });
  240. // create release notes
  241. gulp.task(task.notes, false, function() {
  242. return gulp.src(release.templates.notes)
  243. .pipe(plumber())
  244. .pipe(flatten())
  245. // Remove release notes for lines not mentioning component
  246. .pipe(replace(regExp.match.unrelatedNotes, regExp.replace.unrelatedNotes))
  247. .pipe(replace(regExp.match.whitespace, regExp.replace.whitespace))
  248. .pipe(replace(regExp.match.spacedVersions, regExp.replace.spacedVersions))
  249. .pipe(replace(regExp.match.spacedLists, regExp.replace.spacedLists))
  250. .pipe(replace(regExp.match.trim, regExp.replace.trim))
  251. .pipe(gulp.dest(outputDirectory))
  252. ;
  253. });
  254. // Creates meteor package.js
  255. gulp.task(task.meteor, function() {
  256. var
  257. filenames = ''
  258. ;
  259. return gulp.src(manifest.component)
  260. .pipe(concatFileNames('empty.txt', concatSettings))
  261. .pipe(tap(function(file) {
  262. filenames += file.contents;
  263. }))
  264. .on('end', function() {
  265. gulp.src(manifest.assets)
  266. .pipe(concatFileNames('empty.txt', concatSettings))
  267. .pipe(tap(function(file) {
  268. filenames += file.contents;
  269. }))
  270. .on('end', function() {
  271. // remove trailing slash
  272. filenames = filenames.replace(regExp.match.trailingComma, '').trim();
  273. gulp.src(release.templates.meteor.component)
  274. .pipe(plumber())
  275. .pipe(flatten())
  276. .pipe(replace(regExp.match.name, regExp.replace.name))
  277. .pipe(replace(regExp.match.titleName, regExp.replace.titleName))
  278. .pipe(replace(regExp.match.version, version))
  279. .pipe(replace(regExp.match.files, filenames))
  280. .pipe(rename(release.files.meteor))
  281. .pipe(gulp.dest(outputDirectory))
  282. ;
  283. })
  284. ;
  285. })
  286. ;
  287. });
  288. // synchronous tasks in orchestrator? I think not
  289. gulp.task(task.all, false, function(callback) {
  290. runSequence([
  291. task.repo,
  292. task.npm,
  293. task.bower,
  294. task.readme,
  295. task.package,
  296. task.composer,
  297. task.notes,
  298. task.meteor
  299. ], callback);
  300. });
  301. tasks.push(task.all);
  302. })(component);
  303. }
  304. runSequence(tasks, callback);
  305. };