gulpfile.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. const { src, dest, watch, series, parallel } = require('gulp')
  2. const fs = require('fs-extra')
  3. const util = require('util')
  4. const path = require('path')
  5. const exec = util.promisify(require('child_process').exec)
  6. const rename = require('gulp-rename')
  7. const esbuild = require('esbuild')
  8. const through = require('through2')
  9. const source = {
  10. css : 'source/css',
  11. js : 'source/js',
  12. }
  13. const compiled = {
  14. css : 'dist/css',
  15. js : 'dist/js',
  16. }
  17. function clean() {
  18. return new Promise(function (resolve) {
  19. for (const [key, value] of Object.entries(compiled)) {
  20. fs.emptyDirSync(value)
  21. }
  22. resolve()
  23. })
  24. }
  25. let filtered_css = []
  26. function css() {
  27. return new Promise(async function (resolve) {
  28. if (filtered_css.length) {
  29. for (const file of filtered_css) {
  30. const dest = file.replace(
  31. path.join(__dirname, source.css),
  32. path.join(__dirname, compiled.css)
  33. ).slice(0, -4) + 'css'
  34. await exec(`sass --source-map --embed-sources ${file} ${dest} --quiet`).catch(err => console.log(err.stderr))
  35. }
  36. } else {
  37. await exec(`sass --source-map --embed-sources ${source.css}:${compiled.css} --quiet`).catch(err => console.log(err.stderr))
  38. }
  39. resolve()
  40. })
  41. }
  42. function css_watch() {
  43. watch(source.css).on('all', async function (event, target) {
  44. const obj = path.parse(target)
  45. let targets = []
  46. switch (event) {
  47. case 'add':
  48. case 'change':
  49. if (obj.name.startsWith('_')) {
  50. await new Promise(async function (resolve) {
  51. src(`${source.css}/**/!(_*).scss`)
  52. .pipe(through.obj(function (file, enc, callback) {
  53. const content = file.contents.toString().split(/\r?\n/).filter(i => i.startsWith('@import')).join('')
  54. if (content.includes(`${obj.name.substring(1)}'`) || content.includes(`${obj.name.substring(1)}"`)) {
  55. targets.push(file.path)
  56. }
  57. return callback()
  58. }))
  59. .on('finish', resolve)
  60. })
  61. } else if (obj.ext === '.scss') {
  62. targets.push(path.join(__dirname, obj.dir, obj.base))
  63. }
  64. break;
  65. case 'unlink':
  66. const removedTarget = path.join(__dirname, target).replace(
  67. path.join(__dirname, source.css),
  68. path.join(__dirname, compiled.css),
  69. ).slice(0, -4) + 'css'
  70. fs.removeSync(removedTarget)
  71. fs.removeSync(removedTarget + '.map')
  72. fs.removeSync(removedTarget.slice(0, -3) + 'min.css')
  73. break;
  74. }
  75. filtered_css = targets
  76. })
  77. return watch(source.css, css)
  78. }
  79. function css_prefix() {
  80. return new Promise(async function (resolve) {
  81. await exec(`npx postcss ${compiled.css}/*.css !${compiled.css}/*.min.css --use autoprefixer --map --replace`).catch(err => console.log(err.stderr))
  82. resolve()
  83. })
  84. }
  85. function css_minify() {
  86. return src(`${compiled.css}/!(*.min).css`)
  87. .pipe(through.obj(function (file, enc, callback) {
  88. let content = file.contents.toString()
  89. content = esbuild.transformSync(content, {
  90. loader: 'css',
  91. minify: true,
  92. }).code
  93. file.contents = Buffer.from(content)
  94. this.push(file)
  95. return callback()
  96. }))
  97. .pipe(rename({ suffix: '.min' }))
  98. .pipe(dest(compiled.css))
  99. }
  100. let filtered_js = []
  101. function js() {
  102. return src(`${source.js}/**/*.js`)
  103. .pipe(through.obj(function (file, enc, callback) {
  104. if (pass(file.path, filtered_js)) {
  105. let content = file.contents.toString()
  106. content = esbuild.transformSync(content).code
  107. file.contents = Buffer.from(content)
  108. this.push(file)
  109. }
  110. return callback()
  111. }))
  112. .pipe(dest(compiled.js))
  113. }
  114. function js_watch() {
  115. watch(source.js).on('all', async function (event, target) {
  116. const obj = path.parse(target)
  117. let targets = []
  118. switch (event) {
  119. case 'add':
  120. case 'change':
  121. if (obj.ext === '.js') {
  122. targets.push(path.join(__dirname, obj.dir, obj.base))
  123. }
  124. break;
  125. case 'unlink':
  126. const removedTarget = path.join(__dirname, target).replace(
  127. path.join(__dirname, source.js),
  128. path.join(__dirname, compiled.js),
  129. )
  130. fs.removeSync(removedTarget)
  131. fs.removeSync(removedTarget.slice(0, -2) + 'min.js')
  132. break;
  133. }
  134. filtered_js = targets
  135. })
  136. return watch(source.js, js)
  137. }
  138. function js_minify() {
  139. return src(`${compiled.js}/!(*.min).js`)
  140. .pipe(through.obj(function (file, enc, callback) {
  141. let content = file.contents.toString()
  142. content = esbuild.transformSync(content, {
  143. minify: true,
  144. }).code
  145. file.contents = Buffer.from(content)
  146. this.push(file)
  147. return callback()
  148. }))
  149. .pipe(rename({ suffix: '.min' }))
  150. .pipe(dest(compiled.js))
  151. }
  152. function pass(item, items) {
  153. if (items.length === 0) {
  154. return true
  155. } else {
  156. return items.includes(item)
  157. }
  158. }
  159. exports.css = css
  160. exports.css_watch = css_watch
  161. exports.css_prefix = css_prefix
  162. exports.css_minify = css_minify
  163. exports.js = js
  164. exports.js_watch = js_watch
  165. exports.js_minify = js_minify
  166. exports.dev = parallel(css_watch, js_watch)
  167. exports.build = series(
  168. clean,
  169. parallel(
  170. series(
  171. css,
  172. css_prefix,
  173. css_minify,
  174. ),
  175. series(
  176. js,
  177. js_minify,
  178. ),
  179. )
  180. )