mediac 1.8.0 → 1.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,8 +24,8 @@ import * as core from '../lib/core.js'
24
24
  import * as log from '../lib/debug.js'
25
25
  import * as mf from '../lib/file.js'
26
26
  import * as helper from '../lib/helper.js'
27
- import tryfp from '../lib/tryfp.js'
28
- import { calculateScale, compressImage } from "./cmd_shared.js"
27
+ import * as tryfp from '../lib/tryfp.js'
28
+ import { applyFileNameRules, calculateScale, compressImage } from "./cmd_shared.js"
29
29
 
30
30
  //
31
31
  export { aliases, builder, command, describe, handler }
@@ -40,11 +40,11 @@ const WIDTH_DEFAULT = 6000
40
40
 
41
41
  const builder = function addOptions(ya, helpOrVersionSet) {
42
42
  return ya
43
- .option("purge", {
43
+ .option("delete-source-files", {
44
44
  alias: "p",
45
45
  type: "boolean",
46
46
  default: false,
47
- description: "Purge original image files",
47
+ description: "Delete original image files after compress",
48
48
  })
49
49
  // 输出目录,默认输出文件与原文件同目录
50
50
  .option("output", {
@@ -52,6 +52,32 @@ const builder = function addOptions(ya, helpOrVersionSet) {
52
52
  describe: "Folder store ouput files",
53
53
  type: "string",
54
54
  })
55
+ // 正则,包含文件名规则
56
+ .option("include", {
57
+ alias: "I",
58
+ type: "string",
59
+ description: "filename include pattern",
60
+ })
61
+ //字符串或正则,不包含文件名规则
62
+ // 如果是正则的话需要转义
63
+ .option("exclude", {
64
+ alias: "E",
65
+ type: "string",
66
+ description: "filename exclude pattern ",
67
+ })
68
+ // 默认启用正则模式,禁用则为字符串模式
69
+ .option("regex", {
70
+ alias: 're',
71
+ type: "boolean",
72
+ default: true,
73
+ description: "match filenames by regex pattern",
74
+ })
75
+ // 需要处理的扩展名列表,默认为常见视频文件
76
+ .option("extensions", {
77
+ alias: "e",
78
+ type: "string",
79
+ describe: "include files by extensions (eg. .wav|.flac)",
80
+ })
55
81
  // 压缩后的文件后缀,默认为 _Z4K
56
82
  .option("suffix", {
57
83
  alias: "S",
@@ -59,10 +85,10 @@ const builder = function addOptions(ya, helpOrVersionSet) {
59
85
  type: "string",
60
86
  default: "_Z4K",
61
87
  })
62
- .option("purge-only", {
88
+ .option("delete-source-files-only", {
63
89
  type: "boolean",
64
90
  default: false,
65
- description: "Just delete original image files only",
91
+ description: "Just delete original image files only, no compression",
66
92
  })
67
93
  // 是否覆盖已存在的压缩后文件
68
94
  .option("force", {
@@ -118,12 +144,7 @@ const handler = cmdCompress
118
144
  async function cmdCompress(argv) {
119
145
  const testMode = !argv.doit
120
146
  const logTag = "cmdCompress"
121
- const root = path.resolve(argv.input)
122
- assert.strictEqual("string", typeof root, "root must be string")
123
- if (!root || !(await fs.pathExists(root))) {
124
- log.error(logTag, `Invalid Input: '${root}'`)
125
- throw new Error(`Invalid Input: ${root}`)
126
- }
147
+ const root = await helper.validateInput(argv.input)
127
148
  if (!testMode) {
128
149
  log.fileLog(`Root:${root}`, logTag)
129
150
  log.fileLog(`Argv:${JSON.stringify(argv)}`, logTag)
@@ -133,8 +154,8 @@ async function cmdCompress(argv) {
133
154
  const quality = argv.quality || QUALITY_DEFAULT
134
155
  const minFileSize = (argv.size || SIZE_DEFAULT) * 1024
135
156
  const maxWidth = argv.width || WIDTH_DEFAULT
136
- const purgeOnly = argv.purgeOnly || false
137
- const purgeSource = argv.purge || false
157
+ const purgeOnly = argv.deleteSourceFilesOnly || false
158
+ const purgeSource = argv.deleteSourceFiles || false
138
159
  log.show(`${logTag} input:`, root)
139
160
  // 如果有force标志,就不过滤文件名
140
161
  const RE_THUMB = argv.force ? /@_@/ : /Z4K|P4K|M4K|feature|web|thumb$/i
@@ -152,8 +173,10 @@ async function cmdCompress(argv) {
152
173
  log.showYellow(logTag, "no files found, abort.")
153
174
  return
154
175
  }
176
+ // 应用文件名过滤规则
177
+ files = await applyFileNameRules(files, argv)
155
178
  log.show(logTag, `total ${files.length} files found (all)`)
156
- if (files.length === 0) {
179
+ if (!files || files.length === 0) {
157
180
  log.showYellow("Nothing to do, abort.")
158
181
  return
159
182
  }
@@ -317,10 +340,11 @@ async function preCompress(f) {
317
340
  } else {
318
341
  if (im?.exif) {
319
342
  log.info(logTag, "force:", fileDst)
320
- const md = exif(im.exif)?.Image
343
+ const [err, iexif] = tryfp.tryCatch(exif)(im.exif)
321
344
  // 跳过以前由mediac压缩过的图片,避免重复压缩
322
- if (!f.force) {
323
- if (md.Copyright?.includes("mediac")
345
+ if (!f.force && iexif?.Image) {
346
+ const md = iexif?.Image
347
+ if (md?.Copyright?.includes("mediac")
324
348
  || md.Software?.includes("mediac")
325
349
  || md.Artist?.includes("mediac") && !f.force) {
326
350
  log.info(logTag, "skip:", fileDst)
@@ -339,12 +363,12 @@ async function preCompress(f) {
339
363
  }
340
364
 
341
365
  if (err) {
342
- log.warn(logTag, "sharp", error.message, fileSrc)
343
- log.fileLog(`SharpErr: ${f.index} <${fileSrc}> sharp:${error.message}`, logTag)
366
+ log.warn(logTag, "sharp", err.message, fileSrc)
367
+ log.fileLog(`SharpErr: ${f.index} <${fileSrc}> sharp:${err.message}`, logTag)
344
368
  return
345
369
  }
346
370
 
347
- const { dstWidth, dstHeight } = calculateImageScale(im.width, im.height, maxWidth)
371
+ const { dstWidth, dstHeight } = calculateScale(im.width, im.height, maxWidth)
348
372
  if (f.total < 1000 || f.index > f.total - 1000) {
349
373
  log.show(logTag, `${f.index}/${f.total}`,
350
374
  helper.pathShort(fileSrc),
package/cmd/cmd_dcim.js CHANGED
@@ -11,7 +11,7 @@ import fs from 'fs-extra'
11
11
  import inquirer from "inquirer"
12
12
  import path from "path"
13
13
 
14
- import { renameFiles } from "./cmd_shared.js"
14
+ import { addEntryProps, renameFiles } from "./cmd_shared.js"
15
15
 
16
16
  import * as log from '../lib/debug.js'
17
17
  import * as exif from '../lib/exif.js'
@@ -136,6 +136,7 @@ const handler = async function cmdRename(argv) {
136
136
  log.showYellow(LOG_TAG, "Nothing to do, exit now.")
137
137
  return
138
138
  }
139
+ files = addEntryProps(files)
139
140
  log.show(
140
141
  LOG_TAG,
141
142
  `Total ${files.length} media files ready to rename by exif`,
package/cmd/cmd_decode.js CHANGED
@@ -60,7 +60,7 @@ const handler = async function cmdDecode(argv) {
60
60
  }
61
61
  const fromEnc = argv.fromEnc?.length > 0 ? [argv.fromEnc] : ENC_LIST
62
62
  const toEnc = argv.toEnc?.length > 0 ? [argv.toEnc] : ENC_LIST
63
- const threhold = log.isVerbose() ? 1 : 50
63
+ const threhold = log.isVerbose() ? 0 : 50
64
64
  log.show(logTag, `Input:`, strArgs)
65
65
  log.show(logTag, `fromEnc:`, JSON.stringify(fromEnc))
66
66
  log.show(logTag, `toEnc:`, JSON.stringify(toEnc))
@@ -88,19 +88,19 @@ function showResults(r) {
88
88
  let cr = chardet.analyse(Buffer.from(str))
89
89
  cr = cr.filter(ct => ct.confidence >= 70)
90
90
  cr?.length > 0 && print('Encoding', cr)
91
- print('String', Array.from(str))
92
- print('Unicode', Array.from(str).map(c => c.codePointAt(0).toString(16)))
93
- const badUnicode = enc.checkBadUnicode(str)
91
+ // print('String', Array.from(str))
92
+ // print('Unicode', Array.from(str).map(c => c.codePointAt(0).toString(16)))
93
+ const badUnicode = enc.checkBadUnicode(str, true)
94
94
  badUnicode?.length > 0 && log.show('badUnicode:', badUnicode)
95
- log.info(`MESSY_UNICODE=${enc.REGEX_MESSY_UNICODE.test(str)}`,
96
- `MESSY_CJK=${enc.REGEX_MESSY_CJK.test(str)}`)
97
- log.info(`OnlyJapanese=${unicode.strOnlyJapanese(str)}`,
98
- `OnlyJpHan=${unicode.strOnlyJapaneseHan(str)}`,
99
- `HasHiraKana=${unicode.strHasHiraKana(str)}`
100
- )
101
- log.info(`HasHangul=${unicode.strHasHangul(str)}`,
102
- `OnlyHangul=${unicode.strOnlyHangul(str)}`)
103
- log.info(`HasChinese=${unicode.strHasChinese(str)}`,
104
- `OnlyChinese=${unicode.strOnlyChinese(str)}`,
105
- `OnlyChn3500=${enc.RE_CHARS_MOST_USED.test(str)}`)
95
+ // log.info(`MESSY_UNICODE=${enc.REGEX_MESSY_UNICODE.test(str)}`,
96
+ // `MESSY_CJK=${enc.REGEX_MESSY_CJK.test(str)}`)
97
+ // log.info(`OnlyJapanese=${unicode.strOnlyJapanese(str)}`,
98
+ // `OnlyJpHan=${unicode.strOnlyJapaneseHan(str)}`,
99
+ // `HasHiraKana=${unicode.strHasHiraKana(str)}`
100
+ // )
101
+ // log.info(`HasHangul=${unicode.strHasHangul(str)}`,
102
+ // `OnlyHangul=${unicode.strOnlyHangul(str)}`)
103
+ // log.info(`HasChinese=${unicode.strHasChinese(str)}`,
104
+ // `OnlyChinese=${unicode.strOnlyChinese(str)}`,
105
+ // `OnlyChn3500=${enc.RE_CHARS_MOST_USED.test(str)}`)
106
106
  }