暫無描述

gulpfile.js 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. const gulp = require('gulp');
  2. const pkg = require('./package.json');
  3. const corePkg = require('../package.json');
  4. const merge = require('event-stream').merge;
  5. const browserSync = require('browser-sync').create();
  6. const $ = require('gulp-load-plugins')();
  7. const eco = require('eco');
  8. const fs = require('fs');
  9. const ancss = require('@onsenui/ancss');
  10. const cssnextPlugin = require('postcss-cssnext');
  11. const reporter = require('postcss-reporter');
  12. const historyApiFallback = require('connect-history-api-fallback');
  13. const {rollup} = require('rollup');
  14. const babel = require('rollup-plugin-babel');
  15. const commonjs = require('rollup-plugin-commonjs');
  16. const glob = require('glob');
  17. const rimraf = require('rimraf');
  18. const path = require('path');
  19. const yaml = require('js-yaml');
  20. // Include these plugins outside $ to fix gulp-hub
  21. const plumber = require('gulp-plumber');
  22. const postcss = require('gulp-postcss');
  23. const stylelintPlugin = require('gulp-stylelint');
  24. const prefix = __dirname + '/../build/css/';
  25. const babelrc = Object.assign({}, corePkg.babel);
  26. babelrc.babelrc = babelrc.presets[0][1].modules = false;
  27. babelrc.exclude = 'node_modules/**';
  28. const cwdOption = {
  29. cwd: __dirname // makes sure the correct relative path is used when tasks are run from main OnsenUI gulpfile
  30. };
  31. ////////////////////////////////////////
  32. // build-css
  33. ////////////////////////////////////////
  34. gulp.task('build-css', gulp.series(cssClean, stylelint, cssnext, cssmin));
  35. ////////////////////////////////////////
  36. // build
  37. ////////////////////////////////////////
  38. gulp.task('build', gulp.series('build-css', generatePreview));
  39. ////////////////////////////////////////
  40. // stylelint
  41. ////////////////////////////////////////
  42. function stylelint() {
  43. return gulp.src([
  44. './src/**/*.css',
  45. '!./src/components/combination.css', // not following BEM
  46. '!./src/iphonex-support/**/*.css' // not following BEM
  47. ], cwdOption)
  48. .pipe(stylelintPlugin({
  49. failAfterError: false,
  50. reporters: [{formatter: 'string', console: true}],
  51. configFile: path.join(__dirname, 'stylelint.config.js') // uses css-components/stylelint.config.js even when run from main gulpfile
  52. }));
  53. }
  54. ////////////////////////////////////////
  55. // cssmin
  56. ////////////////////////////////////////
  57. function cssmin() {
  58. return gulp.src(prefix + '{*-,}onsen-css-components.css')
  59. .pipe($.cssmin())
  60. .pipe($.rename({suffix: '.min'}))
  61. //.pipe(gulp.dest('./build/'))
  62. .pipe(gulp.dest(prefix));
  63. }
  64. ////////////////////////////////////////
  65. // cssnext
  66. ////////////////////////////////////////
  67. function cssnext() {
  68. const plugins = [
  69. require('postcss-import'),
  70. require('postcss-base64')({
  71. extensions: ['.svg'],
  72. root: __dirname + '/src/components/'
  73. }),
  74. cssnextPlugin({
  75. browsers: babelrc.presets[0][1].targets.browsers,
  76. }),
  77. reporter({
  78. clearAllMessages: true,
  79. clearReportedMessages: true,
  80. throwError: false
  81. })
  82. ];
  83. return gulp.src('src/{*-,}onsen-css-components.css', cwdOption)
  84. //.pipe(plumber()) // this was causing the task to never complete with gulp 4, but why...?
  85. .pipe(postcss(plugins))
  86. //.pipe(gulp.dest('./build/'))
  87. .pipe(gulp.dest(prefix))
  88. .pipe(browserSync.stream());
  89. }
  90. gulp.task('cssnext', gulp.series(stylelint, cssnext));
  91. function cssClean(done) {
  92. rimraf.sync(__dirname + '/build/{*-,}onsen-css-components.css');
  93. rimraf.sync(__dirname + '/build/{*-,}onsen-css-components.min.css');
  94. rimraf.sync(prefix + '/{*-,}onsen-css-components.css');
  95. rimraf.sync(prefix + '/{*-,}onsen-css-components.min.css');
  96. done();
  97. }
  98. gulp.task('css-clean', cssClean);
  99. ////////////////////////////////////////
  100. // generate-preview
  101. ////////////////////////////////////////
  102. let lastMarkupToken = '';
  103. function generatePreview(done) {
  104. const components = parseComponents();
  105. const markupToken = identifyComponentsMarkup(components);
  106. if (markupToken !== lastMarkupToken) {
  107. gulp.series(previewAssets, previewJs, (done) => {
  108. generate(components);
  109. browserSync.reload();
  110. lastMarkupToken = markupToken;
  111. done();
  112. })();
  113. done();
  114. } else {
  115. lastMarkupToken = markupToken;
  116. done();
  117. }
  118. }
  119. function generatePreviewForce(done) {
  120. generate(parseComponents());
  121. browserSync.reload();
  122. done();
  123. }
  124. exports['generate-preview-force'] = gulp.series(previewAssets, previewJs, generatePreviewForce);
  125. function generate(components) {
  126. const template = fs.readFileSync(__dirname + '/previewer-src/index.html.eco', 'utf-8');
  127. const patterns = yaml.safeLoadAll(fs.readFileSync(__dirname + '/patterns.yaml', 'utf-8'));
  128. const themes = glob.sync(__dirname + '/build/{*-,}onsen-css-components.css').map(filePath => path.basename(filePath, '.css'));
  129. const toJSON = JSON.stringify.bind(JSON);
  130. fs.writeFileSync(__dirname + '/build/index.html', eco.render(template, {toJSON, components, themes, patterns}), 'utf-8');
  131. }
  132. function identifyComponentsMarkup(componentsJSON) {
  133. const token = componentsJSON.map(component => {
  134. return component.annotation.markup;
  135. }).join('');
  136. return token;
  137. }
  138. function parseComponents() {
  139. const css = fs.readFileSync(__dirname + '/build/onsen-css-components.css', 'utf-8');
  140. const components = ancss.parse(css, {detect: line => line.match(/^~/)});
  141. return components || [];
  142. }
  143. ////////////////////////////////////////
  144. // preview-assets
  145. ////////////////////////////////////////
  146. function previewAssets() {
  147. return gulp.src('previewer-src/*.{svg,css}')
  148. .pipe(gulp.dest('./build/'));
  149. }
  150. ////////////////////////////////////////
  151. // preview-js
  152. ////////////////////////////////////////
  153. function previewJs() {
  154. return rollup({
  155. input: 'previewer-src/app.js',
  156. plugins: [
  157. commonjs,
  158. babel(babelrc)
  159. ]
  160. })
  161. .then(bundle => {
  162. return bundle.write({
  163. file: 'build/app.gen.js',
  164. format: 'umd',
  165. sourcemap: 'inline'
  166. });
  167. });
  168. }
  169. ////////////////////////////////////////
  170. // reset-console
  171. ////////////////////////////////////////
  172. function reset(done) {
  173. process.stdout.write('\x1Bc');
  174. done();
  175. }
  176. const outputDevServerInfo = (() => {
  177. let defer = true;
  178. return function () {
  179. if (defer) {
  180. setTimeout(() => {
  181. output();
  182. defer = true;
  183. }, 60);
  184. defer = false;
  185. }
  186. }
  187. function output() {
  188. const localUrl = browserSync.getOption('urls').get('local');
  189. const externalUrl = browserSync.getOption('urls').get('external');
  190. console.log('\nAccess URLs:');
  191. console.log(' Local:', $.util.colors.magenta(localUrl));
  192. console.log(' External:', $.util.colors.magenta(externalUrl));
  193. console.log();
  194. displayBuildCSSInfo();
  195. }
  196. })();
  197. function displayBuildCSSInfo() {
  198. console.log('Built CSS Files:')
  199. getCSSPaths().forEach(cssPath => {
  200. console.log(' ' + $.util.colors.magenta(cssPath));
  201. });
  202. function getCSSPaths() {
  203. return glob.sync(__dirname + '/build/{*-,}onsen-css-components.css').map(cssPath => {
  204. return '.' + path.sep + path.relative(__dirname, cssPath);
  205. });
  206. }
  207. }
  208. function getCSSPaths() {
  209. return glob.sync(__dirname + '/build/{*-,}onsen-css-components.css').map(cssPath => {
  210. return '.' + path.sep + path.relative(__dirname, cssPath);
  211. });
  212. }
  213. ////////////////////////////////////////
  214. // serve
  215. ////////////////////////////////////////
  216. function serve(done) {
  217. gulp.watch(['src/**/*.css'], () => {
  218. reset();
  219. gulp.series('build-css', 'generate-preview', outputDevServerInfo);
  220. });
  221. gulp.watch(['previewer-src/**', 'patterns.yaml'], () => {
  222. reset();
  223. gulp.series('generate-preview-force', outputDevServerInfo)
  224. });
  225. browserSync.emitter.on('init', outputDevServerInfo);
  226. browserSync.init({
  227. logLevel: 'silent',
  228. ui: false,
  229. port: 4321,
  230. notify: false,
  231. server: {
  232. baseDir: __dirname + '/build',
  233. middleware: [historyApiFallback()],
  234. },
  235. startPath: '/',
  236. open: false
  237. });
  238. }
  239. exports.serve = gulp.series('build', serve);