gulp-sharp-optimize-images

Форк
0
138 строк · 3.6 Кб
1
import { obj } from 'through2'
2
import sharp from 'sharp'
3
import Vinyl from 'vinyl'
4
import chalk from 'chalk'
5
import path from 'path'
6

7
const
8
  ALLOWED_EXTENSIONS = [
9
    '.gif',
10
    '.png',
11
    '.jpg', '.jpeg',
12
    '.webp',
13
    '.avif',
14
    '.tiff',
15
    '.heif',
16
  ],
17
  DEFAULT_CONVERSION_OPTIONS = {
18
    quality: 90,
19
    lossless: false,
20
    chromaSubsampling: '4:2:0',
21
  },
22
  DEFAULT_SHARP_OPTIONS = {
23
    animated: true,
24
    limitInputPixels: false,
25
  }
26

27

28
export default function sharpOptimizeImages(options) {
29
  let logLevel = options.logLevel ?? 'small'
30
  delete options.logLevel
31
  let optionObjects = Object.entries(options)
32

33
  return obj(async function (file, enc, callback) {
34
    if (!file) return callback(null, file)
35

36
    if (typeof options !== 'object')
37
      throw new Error('Invalid parameters, they must be an object.')
38

39
    if (!ALLOWED_EXTENSIONS.includes(file.extname)) {
40
      logAboutSuccessfulCopy(file, logLevel)
41
      return callback(null, file)
42
    }
43

44
    let originalFileExtname = file.extname.split('.').at(-1)
45

46

47
    for (let [format, props] of optionObjects) {
48
      let [convertFrom, convertTo] = format.split('_to_')
49

50
      if (!extnamesIsCorrect(convertFrom, convertTo)) {
51
        throw new Error('Invalid name of an object! Make sure you have spelled the extension names correctly.')
52
      }
53

54
      // Checking that the file has not a suitable extension
55
      if (convertTo && `.${convertFrom}` != file.extname) continue
56

57
      //? For general conversion rules such as png: {}
58
      if (!convertTo) {
59
        this.push(await convert(file, convertFrom, props))
60
        logAboutSuccessfulConversion(file, convertFrom, logLevel)
61

62
        if (props.alsoProcessOriginal) {
63
          this.push(await convert(file, originalFileExtname, props))
64
          logAboutSuccessfulConversion(file, originalFileExtname, logLevel)
65
        }
66
      }
67
      //? For specific conversion rules such as png_to_webp: {}
68
      else {
69
        this.push(await convert(file, convertTo, props))
70

71
        logAboutSuccessfulConversion(file, convertTo, logLevel)
72
      }
73
    }
74

75
    return callback()
76
  })
77
}
78

79
async function convert(file, newFileFormat, options) {
80
  if (newFileFormat == 'heif')
81
    options.compression = 'av1'
82

83
  let sharpBuffer =
84
    await sharp(file.path, DEFAULT_SHARP_OPTIONS)
85
      .toFormat(newFileFormat, Object.assign(DEFAULT_CONVERSION_OPTIONS, options))
86
      .toBuffer()
87

88
  return toVinyl(sharpBuffer, newFileFormat, file)
89
}
90

91
function toVinyl(buffer, newFileFormat, file) {
92
  let newFileName = file.basename.substr(0, file.basename.lastIndexOf('.'))
93
    + '.' + newFileFormat
94
 
95
  return new Vinyl({
96
    cwd: file.cwd,
97
    base: file.base,
98
    path: path.join(file.dirname, newFileName),
99
    contents: buffer,
100
  })
101
}
102

103

104
function extnamesIsCorrect(...extnames) {
105
  for (let extname of extnames) {
106
    if (extname && !ALLOWED_EXTENSIONS.includes('.' + extname))
107
      return false
108
  }
109

110
  return true
111
}
112

113
function logAboutSuccessfulConversion(file, newFileExtname, logLevel) {
114
  let filename = file.basename.split('.')[0]
115

116
  if (logLevel == 'full')
117
    console.log(
118
      'The file ' + chalk.green(file.path)
119
      + ' was processed to '
120
      + chalk.green(filename + '.' + chalk.bold(newFileExtname))
121
    )
122
  else if (logLevel == 'small')
123
    console.log(
124
      chalk.green(file.basename) + ' => ' + chalk.green.bold(newFileExtname)
125
    )
126
}
127
function logAboutSuccessfulCopy(file, logLevel) {
128
  if (logLevel == 'full')
129
    console.log(chalk.hex('#FF8800')
130
      (
131
        `The image ${chalk.bold(file.basename)} cannot be processed, so it is copied.`
132
      )
133
    )
134
  else if (logLevel == 'small')
135
    console.log(chalk.hex('#FF8800')
136
      (file.basename + ' => ' + chalk.bold('copied'))
137
    )
138
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.