gulpfile.js 8.1 KB

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