generate.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. var fs = require('fs');
  2. var path = require('path');
  3. var util = require('gulp-util');
  4. var through2 = require('through2');
  5. var dependencies = require('./dependencies.json');
  6. var banner = require('./banner');
  7. var pkg = require('../package.json');
  8. var version = process.env.VERSION || pkg.version;
  9. var IMPORT_SNIPPET = `import {{displayName}} from './{{fileName}}/index'`;
  10. var VAR_SNIPPET = `const {{displayName}} = (selector = '{{selector}}', ctx) => getCtx(selector, ctx)`;
  11. var REFRESHER_VAR_SNIPPET = `const $startWuxRefresher = (selector = '#wux-refresher', ctx) => getCtx(selector, ctx).triggerRefresh()
  12. const $stopWuxRefresher = (selector = '#wux-refresher', ctx) => getCtx(selector, ctx).finishPullToRefresh()
  13. const $stopWuxLoader = (selector = '#wux-refresher', ctx, isEnd) => getCtx(selector, ctx).finishLoadmore(isEnd)`;
  14. var REFRESHER_EXPORT_SNIPPET = ['$startWuxRefresher', '$stopWuxRefresher', '$stopWuxLoader'].join(',\n\t');
  15. function getName(v) {
  16. if (v === 'version') return 'version';
  17. var others = {
  18. actionsheet: 'action-sheet',
  19. keyboard: 'key-board',
  20. countdown: 'count-down',
  21. countup: 'count-up',
  22. };
  23. var toUpper = function (val) {
  24. return `${val.charAt(0).toUpperCase()}${val.slice(1)}`
  25. };
  26. v = others[v] || v;
  27. v = v.split('-').map(function(val) { return toUpper(val) }).join('');
  28. return `$wux${v}`;
  29. }
  30. function getFiles(files) {
  31. return files.map(function(v) {
  32. return {
  33. displayName: getName(v),
  34. fileName: v,
  35. selector: `#wux-${v}`,
  36. }
  37. });
  38. }
  39. function esm(snippet, options) {
  40. return snippet.replace(/{{banner}}/g, options.banner)
  41. .replace(/{{componentImports}}/g, options.componentImports)
  42. .replace(/{{componentAliases}}/g, options.componentAliases)
  43. .replace(/{{componentExports}}/g, options.componentExports)
  44. }
  45. function getFileString(snippet, opts) {
  46. var importFiles = opts.importFiles || [];
  47. var exportFiles = opts.exportFiles || [];
  48. var files = importFiles.concat(exportFiles);
  49. var extra = getFiles(importFiles);
  50. var data = getFiles(exportFiles);
  51. var componentImports = extra.map(function(v) { return inspectFile(IMPORT_SNIPPET, v) }).join('\n');
  52. var componentAliases = `const version = '{{version}}'`.replace(/{{version}}/, version) + '\n';
  53. componentAliases = componentAliases + data.map(function(v) {
  54. if (v.fileName === 'refresher') {
  55. return REFRESHER_VAR_SNIPPET
  56. }
  57. return inspectFile(VAR_SNIPPET, v)
  58. }).join('\n');
  59. var componentExports = ['version'].concat(files).map(function(v) {
  60. if (v === 'refresher') {
  61. return REFRESHER_EXPORT_SNIPPET
  62. }
  63. return getName(v)
  64. }).join(',\n\t');
  65. var options = {
  66. banner: banner.trim(),
  67. componentImports: componentImports,
  68. componentAliases: componentAliases,
  69. componentExports: componentExports,
  70. };
  71. var result = esm(snippet, options);
  72. return result;
  73. }
  74. function getOptions(files) {
  75. var exclude = ['countdown', 'countup'];
  76. var include = ['actionsheet', 'app', 'backdrop', 'toast', 'loading', 'dialog', 'form', 'toptips', 'gallery', 'index', 'notification', 'keyboard', 'select', 'calendar', 'refresher'];
  77. var importFiles = exclude.filter(function(v) { return files.includes(v) });
  78. var exportFiles = files.filter(function(v) { return include.includes(v) });
  79. return {
  80. importFiles: importFiles,
  81. exportFiles: exportFiles,
  82. }
  83. }
  84. function generateScript(files) {
  85. return through2.obj(function(file, encoding, cb) {
  86. // 如果文件为空,不做任何操作,转入下一个操作,即下一个pipe
  87. if (file.isNull()) {
  88. this.push(file)
  89. return cb()
  90. }
  91. // 插件不支持对stream直接操作,抛出异常
  92. if (file.isStream()) {
  93. this.emit('error', new util.PluginError('generateScript', 'Streaming not supported'))
  94. return cb()
  95. }
  96. // 内容转换,处理好后,再转成 Buffer 形式
  97. var snippet = file.contents.toString()
  98. var content = getFileString(snippet, getOptions(files || []))
  99. file.contents = typeof Buffer.from === 'function' ? Buffer.from(content) : new Buffer(content)
  100. // 下面这两句基本是标配,可参考 through2 的 API
  101. this.push(file)
  102. cb()
  103. })
  104. }
  105. function generateStyle(themes, options) {
  106. return through2.obj(function(file, encoding, cb) {
  107. // 如果文件为空,不做任何操作,转入下一个操作,即下一个pipe
  108. if (file.isNull()) {
  109. this.push(file)
  110. return cb()
  111. }
  112. // 插件不支持对stream直接操作,抛出异常
  113. if (file.isStream()) {
  114. this.emit('error', new util.PluginError('generateStyle', 'Streaming not supported'))
  115. return cb()
  116. }
  117. // Include folder
  118. if (options && options.include && !file.relative.match(options.include)) {
  119. return cb()
  120. }
  121. // 内容转换,处理好后,再转成 Buffer 形式
  122. var snippet = file.contents.toString()
  123. var content = inspectLess(snippet, themes || [])
  124. file.contents = typeof Buffer.from === 'function' ? Buffer.from(content) : new Buffer(content)
  125. // 下面这两句基本是标配,可参考 through2 的 API
  126. this.push(file)
  127. cb()
  128. })
  129. }
  130. function generateColor(themes, options) {
  131. return through2.obj(function(file, encoding, cb) {
  132. // 如果文件为空,不做任何操作,转入下一个操作,即下一个pipe
  133. if (file.isNull()) {
  134. this.push(file)
  135. return cb()
  136. }
  137. // 插件不支持对stream直接操作,抛出异常
  138. if (file.isStream()) {
  139. this.emit('error', new util.PluginError('generateStyle', 'Streaming not supported'))
  140. return cb()
  141. }
  142. // 内容转换,处理好后,再转成 Buffer 形式
  143. var snippet = file.contents.toString()
  144. var content = inspectColor(snippet, themes || [])
  145. file.contents = typeof Buffer.from === 'function' ? Buffer.from(content) : new Buffer(content)
  146. // 下面这两句基本是标配,可参考 through2 的 API
  147. this.push(file)
  148. cb()
  149. })
  150. }
  151. function getModifyVars(themes) {
  152. return Object.keys(themes).reduce(function(acc, name) {
  153. acc[name.indexOf('@') === 0 ? name.slice(1) : name] = themes[name]
  154. return acc
  155. }, {})
  156. }
  157. function inspectColor(snippet, themes) {
  158. return Object.keys(themes).reduce(function(acc, name) {
  159. return acc.replace(new RegExp(`('${name}':).+(,)`), `$1 '${themes[name]}'$2`)
  160. }, snippet)
  161. }
  162. function inspectLess(snippet, themes) {
  163. return Object.keys(themes).reduce(function(acc, name) {
  164. return acc.replace(new RegExp(`(\@${name}:).+(;)`), `$1 ${themes[name]}$2`)
  165. }, snippet)
  166. }
  167. function unique(arr) {
  168. return arr.filter(function(v, i) {
  169. return arr.indexOf(v) === i
  170. })
  171. }
  172. function getFilesByName(name) {
  173. if (dependencies[name] === undefined) return [];
  174. return dependencies[name].dependencies.reduce(function(acc, depName) {
  175. return acc.concat(getFilesByName(depName))
  176. }, dependencies[name].files)
  177. }
  178. function getFilesByNames(names) {
  179. return unique(names.reduce(function(acc, name) {
  180. return acc.concat(getFilesByName(name))
  181. }, []))
  182. }
  183. /**
  184. * Create Folder
  185. */
  186. function mkdirs(dirname, callback) {
  187. fs.exists(dirname, function (exists) {
  188. if (exists) {
  189. callback();
  190. } else {
  191. mkdirs(path.dirname(dirname), function () {
  192. fs.mkdir(dirname, callback);
  193. });
  194. }
  195. });
  196. }
  197. /**
  198. * Write File
  199. */
  200. function writeFile(fileName, fileString) {
  201. fs.writeFile(fileName, fileString, function(err) {
  202. if (err) {
  203. console.error('error writeFile:', err);
  204. return;
  205. }
  206. console.log('success writeFile: generate index.js');
  207. });
  208. }
  209. /**
  210. * Inspect File
  211. */
  212. function inspectFile(snippet, options) {
  213. return snippet.replace(/{{displayName}}/g, options.displayName)
  214. .replace(/{{fileName}}/g, options.fileName)
  215. .replace(/{{selector}}/g, options.selector)
  216. }
  217. module.exports.generateScript = generateScript;
  218. module.exports.generateStyle = generateStyle;
  219. module.exports.generateColor = generateColor;
  220. module.exports.getModifyVars = getModifyVars;
  221. module.exports.getFilesByNames = getFilesByNames;
  222. module.exports.mkdirs = mkdirs;