gulpfile.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* eslint-env node */
  2. const autoprefix = require('autoprefixer')
  3. const browserSync = require('browser-sync').create()
  4. const del = require('del')
  5. const { src, dest, lastRun, watch, series, parallel } = require('gulp')
  6. const cleanCss = require('gulp-clean-css')
  7. const eslint = require('gulp-eslint-new')
  8. const fileinclude = require('gulp-file-include')
  9. const validator = require('gulp-html')
  10. const gulpIf = require('gulp-if')
  11. const npmDist = require('gulp-npm-dist')
  12. const postcss = require('gulp-postcss')
  13. const rename = require('gulp-rename')
  14. const sass = require('gulp-sass')(require('sass'))
  15. const gulpStylelint = require('gulp-stylelint')
  16. const terser = require('gulp-terser')
  17. const rollup = require('rollup')
  18. const rollupTypescript = require('@rollup/plugin-typescript')
  19. const rtlcss = require('rtlcss')
  20. const pkg = require('./package')
  21. const year = new Date().getFullYear()
  22. const banner = `/*!
  23. * AdminLTE v${pkg.version} (${pkg.homepage})
  24. * Copyright 2014-${year} ${pkg.author}
  25. * Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE)
  26. */`
  27. // Define paths
  28. const paths = {
  29. dist: {
  30. base: './dist/',
  31. css: './dist/css',
  32. js: './dist/js',
  33. html: './dist/pages',
  34. assets: './dist/assets',
  35. vendor: './dist/vendor'
  36. },
  37. src: {
  38. base: './src/',
  39. html: './src/pages/**/*.html',
  40. assets: './src/assets/**/*.*',
  41. partials: './src/partials/**/*.html',
  42. scss: './src/scss',
  43. ts: './src/ts',
  44. nodeModules: './node_modules/'
  45. },
  46. temp: {
  47. base: './.temp/',
  48. css: './.temp/css',
  49. js: './.temp/js',
  50. html: './.temp/pages',
  51. assets: './.temp/assets',
  52. vendor: './.temp/vendor'
  53. }
  54. }
  55. const sassOptions = {
  56. outputStyle: 'expanded',
  57. includePaths: ['./node_modules/']
  58. }
  59. const postcssOptions = [
  60. autoprefix({ cascade: false })
  61. ]
  62. const postcssRtlOptions = [
  63. autoprefix({ cascade: false }),
  64. rtlcss({})
  65. ]
  66. // From here Dev mode will Start
  67. // Lint SCSS
  68. const lintScss = () => src([paths.src.scss + '/**/*.scss'], { since: lastRun(lintScss) })
  69. .pipe(gulpStylelint({
  70. failAfterError: false,
  71. reporters: [
  72. { formatter: 'string', console: true }
  73. ]
  74. }))
  75. // Compile SCSS
  76. const scss = () => src(paths.src.scss + '/adminlte.scss', { sourcemaps: true })
  77. .pipe(sass(sassOptions).on('error', sass.logError))
  78. .pipe(postcss(postcssOptions))
  79. .pipe(dest(paths.temp.css, { sourcemaps: '.' }))
  80. .pipe(browserSync.stream())
  81. // Compile SCSS Dark
  82. const scssDark = () => src(paths.src.scss + '/dark/adminlte-dark-addon.scss', { sourcemaps: true })
  83. .pipe(sass(sassOptions).on('error', sass.logError))
  84. .pipe(postcss(postcssOptions))
  85. .pipe(dest(paths.temp.css + '/dark', { sourcemaps: '.' }))
  86. .pipe(browserSync.stream())
  87. // Lint TS
  88. function isFixed(file) {
  89. // Has ESLint fixed the file contents?
  90. return file.eslint !== null && file.eslint.fixed
  91. }
  92. const lintTs = () => src([paths.src.ts + '/**/*.ts'], { since: lastRun(lintTs) })
  93. .pipe(eslint({ fix: true }))
  94. .pipe(eslint.format())
  95. .pipe(gulpIf(isFixed, dest(paths.src.ts)))
  96. .pipe(eslint.failAfterError())
  97. // Compile TS
  98. const tsCompile = () =>
  99. rollup.rollup({
  100. input: paths.src.ts + '/adminlte.ts',
  101. output: {
  102. banner
  103. },
  104. plugins: [
  105. rollupTypescript()
  106. ]
  107. }).then(bundle => bundle.write({
  108. file: paths.temp.js + '/adminlte.js',
  109. format: 'umd',
  110. name: 'adminlte',
  111. sourcemap: true
  112. }))
  113. const assets = () => src([paths.src.assets])
  114. .pipe(dest(paths.temp.assets))
  115. .pipe(browserSync.stream())
  116. const index = () => src([paths.src.base + '*.html'])
  117. .pipe(fileinclude({
  118. prefix: '@@',
  119. basepath: './src/partials/',
  120. context: {
  121. environment: 'development'
  122. }
  123. }))
  124. .pipe(dest(paths.temp.base))
  125. .pipe(browserSync.stream())
  126. const html = () => src([paths.src.html])
  127. .pipe(fileinclude({
  128. prefix: '@@',
  129. basepath: './src/partials/',
  130. context: {
  131. environment: 'development'
  132. }
  133. }))
  134. .pipe(dest(paths.temp.html))
  135. .pipe(browserSync.stream())
  136. const lintHtml = () => src([paths.temp.html + '/**/*.html', paths.src.base + '*.html'])
  137. .pipe(validator())
  138. const vendor = () => src(npmDist({ copyUnminified: true }), { base: paths.src.nodeModules })
  139. .pipe(dest(paths.temp.vendor))
  140. const serve = () => {
  141. browserSync.init({
  142. server: paths.temp.base
  143. })
  144. watch([paths.src.scss], series(lintScss))
  145. watch([paths.src.scss + '/**/*.scss', '!' + paths.src.scss + '/bootstrap-dark/**/*.scss', '!' + paths.src.scss + '/dark/**/*.scss'], series(scss))
  146. watch([paths.src.scss + '/bootstrap-dark/', paths.src.scss + '/dark/'], series(scssDark))
  147. watch([paths.src.ts], series(lintTs, tsCompile))
  148. watch([paths.src.html, paths.src.base + '*.html', paths.src.partials], series(html, index, lintHtml))
  149. watch([paths.src.assets], series(assets))
  150. }
  151. // From here Dist will Start
  152. // Clean
  153. const cleanDist = () => del([paths.dist.base])
  154. const lintDistScss = () => src([paths.src.scss + '/**/*.scss'])
  155. .pipe(gulpStylelint({
  156. failAfterError: false,
  157. reporters: [
  158. { formatter: 'string', console: true }
  159. ]
  160. }))
  161. // Compile and copy all scss/css
  162. const copyDistCssAll = () => src([paths.src.scss + '/**/*.scss'], {
  163. base: paths.src.scss,
  164. sourcemaps: true
  165. })
  166. .pipe(sass(sassOptions).on('error', sass.logError))
  167. .pipe(postcss(postcssOptions))
  168. .pipe(dest(paths.dist.css, { sourcemaps: '.' }))
  169. const copyDistCssRtl = () => src(paths.dist.css + '/*.css', { sourcemaps: true })
  170. .pipe(postcss(postcssRtlOptions))
  171. .pipe(rename({ suffix: '.rtl' }))
  172. .pipe(dest(paths.dist.css + '/rtl', { sourcemaps: '.' }))
  173. // Minify CSS
  174. const minifyDistCss = () => src([
  175. paths.dist.css + '/**/*.css'
  176. ], {
  177. base: paths.dist.css,
  178. sourcemaps: true
  179. })
  180. .pipe(cleanCss({ format: { breakWith: 'lf' } }))
  181. .pipe(rename({ suffix: '.min' }))
  182. .pipe(dest(paths.dist.css, { sourcemaps: '.' }))
  183. const lintDistTs = () => src([paths.src.ts + '/**/*.ts'])
  184. .pipe(eslint())
  185. .pipe(eslint.failAfterError())
  186. // Compile and copy ts/js
  187. const copyDistJs = () =>
  188. rollup.rollup({
  189. input: paths.src.ts + '/adminlte.ts',
  190. output: {
  191. banner
  192. },
  193. plugins: [
  194. rollupTypescript()
  195. ]
  196. }).then(bundle => bundle.write({
  197. file: paths.dist.js + '/adminlte.js',
  198. format: 'umd',
  199. name: 'adminlte',
  200. sourcemap: true
  201. }))
  202. // Minify JS
  203. // Need to add terser
  204. const minifyDistJs = () =>
  205. src(paths.dist.js + '/adminlte.js', { sourcemaps: true })
  206. .pipe(terser({
  207. compress: {
  208. passes: 2
  209. },
  210. comments: '/^!/'
  211. }))
  212. .pipe(dest(paths.dist.js + '/adminlte.min.js'))
  213. // Copy assets
  214. const copyDistAssets = () => src(paths.src.assets)
  215. .pipe(dest(paths.dist.assets))
  216. // Copy index
  217. const copyDistHtmlIndex = () => src([paths.src.base + '*.html'])
  218. .pipe(fileinclude({
  219. prefix: '@@',
  220. basepath: './src/partials/',
  221. context: {
  222. environment: 'production'
  223. }
  224. }))
  225. .pipe(dest(paths.dist.base))
  226. // Copy Html
  227. const copyDistHtml = () => src([paths.src.html])
  228. .pipe(fileinclude({
  229. prefix: '@@',
  230. basepath: './src/partials/',
  231. context: {
  232. environment: 'production'
  233. }
  234. }))
  235. .pipe(dest(paths.dist.html))
  236. const lintDistHtml = () => src([paths.temp.html + '/**/*.html', paths.src.base + '*.html'])
  237. .pipe(validator())
  238. // Copy node_modules to vendor
  239. const copyDistVendor = () => src(npmDist({ copyUnminified: true }), { base: paths.src.nodeModules })
  240. .pipe(dest(paths.dist.vendor))
  241. const lint = parallel(
  242. lintDistScss,
  243. lintDistTs,
  244. series(copyDistHtmlIndex, copyDistHtml, lintDistHtml)
  245. )
  246. exports.lint = lint
  247. const compile = series(
  248. cleanDist,
  249. parallel(
  250. series(
  251. parallel(copyDistCssAll, copyDistCssRtl),
  252. minifyDistCss
  253. ),
  254. series(copyDistJs, minifyDistJs),
  255. copyDistAssets,
  256. copyDistHtmlIndex,
  257. copyDistHtml,
  258. copyDistVendor
  259. )
  260. )
  261. exports.compile = compile
  262. // For Production Release
  263. exports.production = series(lint, compile)
  264. // Default - Only for light mode AdminLTE
  265. exports.default = series(scss, scssDark, tsCompile, html, index, assets, vendor, serve)