gulpfile.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /* eslint-disable no-console */
  2. /* eslint-disable camelcase */
  3. /* eslint-disable no-undef */
  4. /* eslint-disable unicorn/prefer-module */
  5. const browserSync = require('browser-sync').create()
  6. const cleanCss = require('gulp-clean-css')
  7. const del = require('del')
  8. const esbuild = require('esbuild')
  9. const { ESLint } = require('eslint')
  10. const { src, dest, lastRun, watch, series } = require('gulp')
  11. const fileinclude = require('gulp-file-include')
  12. const npmDist = require('gulp-npm-dist')
  13. const postcss = require('gulp-postcss')
  14. const rename = require('gulp-rename')
  15. const sass = require('gulp-sass')
  16. const sourcemaps = require('gulp-sourcemaps')
  17. const gulpStylelint = require('gulp-stylelint')
  18. const wait = require('gulp-wait')
  19. sass.compiler = require('sass')
  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. img: './dist/assets/img',
  36. vendor: './dist/vendor'
  37. },
  38. base: {
  39. base: './',
  40. node: './node_modules'
  41. },
  42. src: {
  43. base: './src/',
  44. css: './src/css',
  45. html: './src/pages/**/*.html',
  46. assets: './src/assets/**/*.*',
  47. partials: './src/partials/**/*.html',
  48. scss: './src/scss',
  49. ts: './src/ts',
  50. node_modules: './node_modules/',
  51. vendor: './vendor'
  52. },
  53. temp: {
  54. base: './.temp/',
  55. css: './.temp/css',
  56. js: './.temp/js',
  57. html: './.temp/pages',
  58. assets: './.temp/assets',
  59. vendor: './.temp/vendor'
  60. }
  61. }
  62. const sassOptions = {
  63. outputStyle: 'expanded',
  64. includePaths: ['./node_modules/']
  65. }
  66. function postcssOptions() {
  67. return {
  68. map: {
  69. inline: false,
  70. annotation: true,
  71. sourcesContent: true
  72. },
  73. plugins: [
  74. require('autoprefixer')({
  75. cascade: false
  76. })
  77. ]
  78. }
  79. }
  80. function postcssRtlOptions() {
  81. return {
  82. map: {
  83. inline: false,
  84. annotation: true,
  85. sourcesContent: true
  86. },
  87. plugins: [
  88. require('autoprefixer')({
  89. cascade: false
  90. }),
  91. require('rtlcss')({})
  92. ]
  93. }
  94. }
  95. // Compile SCSS
  96. const scss = () => {
  97. return src(paths.src.scss + '/adminlte.scss')
  98. .pipe(wait(500))
  99. .pipe(sourcemaps.init())
  100. .pipe(sass(sassOptions).on('error', sass.logError))
  101. .pipe(postcss(postcssOptions))
  102. .pipe(sourcemaps.write('.'))
  103. .pipe(dest(paths.temp.css))
  104. .pipe(browserSync.stream())
  105. }
  106. // Lint SCSS
  107. const lintScss = () => {
  108. return src([paths.src.scss + '/**/*.scss'], { since: lastRun(lintScss) })
  109. .pipe(gulpStylelint({
  110. reporters: [
  111. { formatter: 'string', console: true }
  112. ]
  113. }))
  114. }
  115. const ts = () => {
  116. return esbuild.build({
  117. entryPoints: [paths.src.ts + '/adminlte.ts'],
  118. banner: {
  119. js: banner
  120. },
  121. bundle: true,
  122. format: 'iife',
  123. sourcemap: true,
  124. target: ['chrome60'],
  125. outfile: paths.temp.js + '/adminlte.js'
  126. }).catch(
  127. error => console.error(error)
  128. )
  129. }
  130. // Lint TS
  131. async function lintTs() {
  132. const eslint = new ESLint()
  133. const results = await eslint.lintFiles([paths.src.ts + '/**/*.ts'])
  134. const formatter = await eslint.loadFormatter('stylish')
  135. const resultText = formatter.format(results)
  136. console.log(resultText)
  137. }
  138. const index = () => {
  139. return src([paths.src.base + '*.html'])
  140. .pipe(fileinclude({
  141. prefix: '@@',
  142. basepath: './src/partials/',
  143. context: {
  144. environment: 'development'
  145. }
  146. }))
  147. .pipe(dest(paths.temp.base))
  148. .pipe(browserSync.stream())
  149. }
  150. const html = () => {
  151. return src([paths.src.html])
  152. .pipe(fileinclude({
  153. prefix: '@@',
  154. basepath: './src/partials/',
  155. context: {
  156. environment: 'development'
  157. }
  158. }))
  159. .pipe(dest(paths.temp.html))
  160. .pipe(browserSync.stream())
  161. }
  162. const assets = () => {
  163. return src([paths.src.assets])
  164. .pipe(dest(paths.temp.assets))
  165. .pipe(browserSync.stream())
  166. }
  167. const vendor = () => {
  168. return src(npmDist({ copyUnminified: true }), { base: paths.src.node_modules })
  169. .pipe(dest(paths.temp.vendor))
  170. }
  171. const serve = () => {
  172. browserSync.init({
  173. server: paths.temp.base
  174. })
  175. watch([paths.src.scss], series(scss))
  176. watch([paths.src.scss], series(lintScss))
  177. watch([paths.src.ts], series(ts))
  178. watch([paths.src.html, paths.src.base + '*.html', paths.src.partials], series(html, index))
  179. watch([paths.src.assets], series(assets))
  180. watch([paths.src.vendor], series(vendor))
  181. }
  182. // Minify CSS
  183. const minifyDistCss = () => {
  184. return src([
  185. paths.dist.css + '/**/*.css'
  186. ], { base: paths.dist.css })
  187. .pipe(sourcemaps.init({ loadMaps: true }))
  188. .pipe(cleanCss())
  189. .pipe(rename({ suffix: '.min' }))
  190. .pipe(sourcemaps.write('.'))
  191. .pipe(dest(paths.dist.css))
  192. }
  193. // Minify JS
  194. const minifyDistJs = () => {
  195. return esbuild.build({
  196. entryPoints: [paths.dist.js + '/adminlte.js'],
  197. format: 'iife',
  198. minify: true,
  199. sourcemap: true,
  200. target: ['chrome60'],
  201. outfile: paths.dist.js + '/adminlte.min.js'
  202. }).catch(
  203. error => console.error(error)
  204. )
  205. }
  206. // Copy assets
  207. const copyDistAssets = () => {
  208. return src(paths.src.assets)
  209. .pipe(dest(paths.dist.assets))
  210. }
  211. // Clean
  212. const cleanDist = () => {
  213. return del([paths.dist.base])
  214. }
  215. // Compile and copy scss/css
  216. const copyDistCss = () => {
  217. return src([paths.src.scss + '/adminlte.scss'])
  218. .pipe(wait(500))
  219. .pipe(sourcemaps.init())
  220. .pipe(sass(sassOptions).on('error', sass.logError))
  221. .pipe(postcss(postcssOptions))
  222. .pipe(sourcemaps.write('.'))
  223. .pipe(dest(paths.dist.css))
  224. }
  225. const copyDistCssDark = () => {
  226. return src([paths.src.scss + '/dark/*.scss'])
  227. .pipe(wait(500))
  228. .pipe(sourcemaps.init())
  229. .pipe(sass(sassOptions).on('error', sass.logError))
  230. .pipe(postcss(postcssOptions))
  231. .pipe(sourcemaps.write('.'))
  232. .pipe(dest(paths.dist.css + '/dark'))
  233. }
  234. const copyDistCssRtl = () => {
  235. return src([
  236. paths.dist.css + '/*.css',
  237. paths.dist.css + '/dark/*.css'
  238. ])
  239. .pipe(wait(500))
  240. .pipe(sourcemaps.init({ loadMaps: true }))
  241. .pipe(postcss(postcssRtlOptions))
  242. .pipe(rename({ suffix: '.rtl' }))
  243. .pipe(sourcemaps.write('.'))
  244. .pipe(dest(paths.dist.css + '/rtl'))
  245. }
  246. // Compile and copy ts/js
  247. const copyDistJs = () => {
  248. return esbuild.build({
  249. entryPoints: [paths.src.ts + '/adminlte.ts'],
  250. banner: {
  251. js: banner
  252. },
  253. bundle: true,
  254. format: 'iife',
  255. sourcemap: true,
  256. target: ['chrome60'],
  257. outfile: paths.dist.js + '/adminlte.js'
  258. }).catch(
  259. error => console.error(error)
  260. )
  261. }
  262. // Copy Html
  263. const copyDistHtml = () => {
  264. return src([paths.src.html])
  265. .pipe(fileinclude({
  266. prefix: '@@',
  267. basepath: './src/partials/',
  268. context: {
  269. environment: 'production'
  270. }
  271. }))
  272. .pipe(dest(paths.dist.html))
  273. }
  274. // Copy index
  275. const copyDistHtmlIndex = () => {
  276. return src([paths.src.base + '*.html'])
  277. .pipe(fileinclude({
  278. prefix: '@@',
  279. basepath: './src/partials/',
  280. context: {
  281. environment: 'production'
  282. }
  283. }))
  284. .pipe(dest(paths.dist.base))
  285. }
  286. // Copy node_modules to vendor
  287. const copyDistVendor = () => {
  288. return src(npmDist({ copyUnminified: true }), { base: paths.src.node_modules })
  289. .pipe(dest(paths.dist.vendor))
  290. }
  291. exports.build = series(lintScss, lintTs, cleanDist, copyDistCss, copyDistCssDark, copyDistCssRtl, minifyDistCss, copyDistJs, minifyDistJs, copyDistHtml, copyDistHtmlIndex, copyDistAssets, copyDistVendor)
  292. // Default
  293. exports.default = series(lintScss, scss, lintTs, ts, html, index, assets, vendor, serve)