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.

320 lines
11 KiB

  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. // config
  33. config = require('../config/user'),
  34. github = require('../config/admin/github'),
  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 = 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.repoRoot + capitalizedComponent,
  60. gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git',
  61. repoURL = 'https://github.com/' + release.org + '/' + repoName + '/',
  62. regExp = {
  63. match : {
  64. // templated values
  65. name : '{component}',
  66. titleName : '{Component}',
  67. version : '{version}',
  68. files : '{files}',
  69. // release notes
  70. spacedVersions : /(###.*\n)\n+(?=###)/gm,
  71. spacedLists : /(^- .*\n)\n+(?=^-)/gm,
  72. trim : /^\s+|\s+$/g,
  73. unrelatedNotes : new RegExp('^((?!(^.*(' + component + ').*$|###.*)).)*$', 'gmi'),
  74. whitespace : /\n\s*\n\s*\n/gm,
  75. // npm
  76. export : /\$\.fn\.\w+\s*=\s*function\(parameters\)\s*{/g,
  77. formExport : /\$\.fn\.\w+\s*=\s*function\(fields, parameters\)\s*{/g,
  78. settingsExport : /\$\.fn\.\w+\.settings\s*=/g,
  79. settingsReference : /\$\.fn\.\w+\.settings/g,
  80. jQuery : /jQuery/g,
  81. },
  82. replace : {
  83. // readme
  84. name : component,
  85. titleName : capitalizedComponent,
  86. // release notes
  87. spacedVersions : '',
  88. spacedLists : '$1',
  89. trim : '',
  90. unrelatedNotes : '',
  91. whitespace : '\n\n',
  92. // npm
  93. export : 'module.exports = function(parameters) {\n var _module = module;\n',
  94. formExport : 'module.exports = function(fields, parameters) {\n var _module = module;\n',
  95. settingsExport : 'module.exports.settings =',
  96. settingsReference : '_module.exports.settings',
  97. jQuery : 'require("jquery")'
  98. }
  99. },
  100. task = {
  101. all : component + ' creating',
  102. repo : component + ' create repo',
  103. bower : component + ' create bower.json',
  104. readme : component + ' create README',
  105. npm : component + ' create NPM Module',
  106. notes : component + ' create release notes',
  107. composer : component + ' create composer.json',
  108. package : component + ' create package.json',
  109. meteor : component + ' create package.js',
  110. },
  111. // paths to includable assets
  112. assetPath = '/assets/**/' + component + '?(s).*'
  113. ;
  114. // copy dist files into output folder adjusting asset paths
  115. gulp.task(task.repo, false, function() {
  116. return gulp.src(release.source + component + '.*')
  117. .pipe(plumber())
  118. .pipe(flatten())
  119. .pipe(replace(release.paths.source, release.paths.output))
  120. .pipe(gulp.dest(outputDirectory))
  121. ;
  122. });
  123. // create npm module
  124. gulp.task(task.npm, false, function() {
  125. return gulp.src(release.source + component + '!(*.min|*.map).js')
  126. .pipe(plumber())
  127. .pipe(flatten())
  128. .pipe(replace(regExp.match.export, regExp.replace.export))
  129. .pipe(replace(regExp.match.formExport, regExp.replace.formExport))
  130. .pipe(replace(regExp.match.settingsExport, regExp.replace.settingsExport))
  131. .pipe(replace(regExp.match.settingsReference, regExp.replace.settingsReference))
  132. .pipe(replace(regExp.match.jQuery, regExp.replace.jQuery))
  133. .pipe(rename('index.js'))
  134. .pipe(gulp.dest(outputDirectory))
  135. ;
  136. });
  137. // create readme
  138. gulp.task(task.readme, false, function() {
  139. return gulp.src(release.templates.readme)
  140. .pipe(plumber())
  141. .pipe(flatten())
  142. .pipe(replace(regExp.match.name, regExp.replace.name))
  143. .pipe(replace(regExp.match.titleName, regExp.replace.titleName))
  144. .pipe(gulp.dest(outputDirectory))
  145. ;
  146. });
  147. // extend bower.json
  148. gulp.task(task.bower, false, function() {
  149. return gulp.src(release.templates.bower)
  150. .pipe(plumber())
  151. .pipe(flatten())
  152. .pipe(jsonEditor(function(bower) {
  153. bower.name = packageName;
  154. bower.description = capitalizedComponent + ' - Semantic UI';
  155. if(isJavascript) {
  156. if(isCSS) {
  157. bower.main = [
  158. component + '.js',
  159. component + '.css'
  160. ];
  161. }
  162. else {
  163. bower.main = [
  164. component + '.js'
  165. ];
  166. }
  167. bower.dependencies = {
  168. jquery: '>=1.8'
  169. };
  170. }
  171. else {
  172. bower.main = [
  173. component + '.css'
  174. ];
  175. }
  176. return bower;
  177. }))
  178. .pipe(gulp.dest(outputDirectory))
  179. ;
  180. });
  181. // extend package.json
  182. gulp.task(task.package, false, function() {
  183. return gulp.src(release.templates.package)
  184. .pipe(plumber())
  185. .pipe(flatten())
  186. .pipe(jsonEditor(function(package) {
  187. if(isJavascript) {
  188. package.dependencies = {
  189. jquery: 'x.x.x'
  190. };
  191. package.main = 'index.js';
  192. }
  193. package.name = packageName;
  194. if(version) {
  195. package.version = version;
  196. }
  197. package.title = 'Semantic UI - ' + capitalizedComponent;
  198. package.description = 'Single component release of ' + component;
  199. package.repository = {
  200. type : 'git',
  201. url : gitURL
  202. };
  203. return package;
  204. }))
  205. .pipe(gulp.dest(outputDirectory))
  206. ;
  207. });
  208. // extend composer.json
  209. gulp.task(task.composer, false, function() {
  210. return gulp.src(release.templates.composer)
  211. .pipe(plumber())
  212. .pipe(flatten())
  213. .pipe(jsonEditor(function(composer) {
  214. if(isJavascript) {
  215. composer.dependencies = {
  216. jquery: 'x.x.x'
  217. };
  218. composer.main = component + '.js';
  219. }
  220. composer.name = 'semantic/' + component;
  221. if(version) {
  222. composer.version = version;
  223. }
  224. composer.description = 'Single component release of ' + component;
  225. return composer;
  226. }))
  227. .pipe(gulp.dest(outputDirectory))
  228. ;
  229. });
  230. // create release notes
  231. gulp.task(task.notes, false, function() {
  232. return gulp.src(release.templates.notes)
  233. .pipe(plumber())
  234. .pipe(flatten())
  235. // Remove release notes for lines not mentioning component
  236. .pipe(replace(regExp.match.unrelatedNotes, regExp.replace.unrelatedNotes))
  237. .pipe(replace(regExp.match.whitespace, regExp.replace.whitespace))
  238. .pipe(replace(regExp.match.spacedVersions, regExp.replace.spacedVersions))
  239. .pipe(replace(regExp.match.spacedLists, regExp.replace.spacedLists))
  240. .pipe(replace(regExp.match.trim, regExp.replace.trim))
  241. .pipe(gulp.dest(outputDirectory))
  242. ;
  243. });
  244. // Creates meteor package.js
  245. gulp.task(task.meteor, function() {
  246. var
  247. fileNames = ''
  248. ;
  249. if(isJavascript) {
  250. fileNames += ' \'' + component + '.js\',\n';
  251. }
  252. if(isCSS) {
  253. fileNames += ' \'' + component + '.css\',\n';
  254. }
  255. return gulp.src(outputDirectory + assetPath, { base: outputDirectory})
  256. .pipe(concatFileNames('/dev/null', {
  257. newline : '',
  258. root : outputDirectory,
  259. prepend : ' \'',
  260. append : '\','
  261. }))
  262. .pipe(tap(function(file) { fileNames += file.contents; }))
  263. .on('end', function(){
  264. gulp.src(release.templates.meteor)
  265. .pipe(plumber())
  266. .pipe(flatten())
  267. .pipe(replace(regExp.match.name, regExp.replace.name))
  268. .pipe(replace(regExp.match.titleName, regExp.replace.titleName))
  269. .pipe(replace(regExp.match.version, version))
  270. .pipe(replace(regExp.match.files, fileNames))
  271. .pipe(rename(release.files.meteor))
  272. .pipe(gulp.dest(outputDirectory))
  273. ;
  274. })
  275. ;
  276. });
  277. // synchronous tasks in orchestrator? I think not
  278. gulp.task(task.all, false, function(callback) {
  279. runSequence([
  280. task.repo,
  281. task.npm,
  282. task.bower,
  283. task.readme,
  284. task.package,
  285. task.composer,
  286. task.notes,
  287. task.meteor
  288. ], callback);
  289. });
  290. tasks.push(task.all);
  291. })(component);
  292. }
  293. runSequence(tasks, callback);
  294. };