From 353356749b0cadd0b696640fb09b7cf0d7fcfdef Mon Sep 17 00:00:00 2001 From: "heecheol.park" Date: Sun, 17 May 2026 21:33:42 +0900 Subject: [PATCH] refactor(cli): extract sanitizeFilename to shared lib/file-utils The same sanitizeFilename implementation lived in both bin/commands/attachments.js and bin/commands/export.js, so any future fix had to be made twice. Move it to lib/file-utils.js and import from both call sites. --- bin/commands/attachments.js | 14 +------------- bin/commands/export.js | 15 +-------------- lib/file-utils.js | 16 ++++++++++++++++ tests/export.test.js | 2 +- 4 files changed, 19 insertions(+), 28 deletions(-) create mode 100644 lib/file-utils.js diff --git a/bin/commands/attachments.js b/bin/commands/attachments.js index 5bb61fb..6a1ebe1 100644 --- a/bin/commands/attachments.js +++ b/bin/commands/attachments.js @@ -2,19 +2,7 @@ const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); const inquirer = require('inquirer'); - -function sanitizeFilename(filename) { - if (!filename || typeof filename !== 'string') { - return 'unnamed'; - } - const stripped = path.basename(filename.replace(/\\/g, '/')); - const cleaned = stripped - // eslint-disable-next-line no-control-regex - .replace(/[\\/:*?"<>|\x00-\x1f]/g, '_') - .replace(/^\.+/, '') - .trim(); - return cleaned || 'unnamed'; -} +const { sanitizeFilename } = require('../../lib/file-utils'); function registerAttachmentCommands(program, { withClient }) { program diff --git a/bin/commands/export.js b/bin/commands/export.js index f51f13c..8a0c62c 100644 --- a/bin/commands/export.js +++ b/bin/commands/export.js @@ -1,6 +1,7 @@ const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); +const { sanitizeFilename } = require('../../lib/file-utils'); const EXPORT_MARKER = '.confluence-export.json'; @@ -18,19 +19,6 @@ function isExportDirectory(fs, path, dir) { return fs.existsSync(path.join(dir, EXPORT_MARKER)); } -function sanitizeFilename(filename) { - if (!filename || typeof filename !== 'string') { - return 'unnamed'; - } - const stripped = path.basename(filename.replace(/\\/g, '/')); - const cleaned = stripped - // eslint-disable-next-line no-control-regex - .replace(/[\\/:*?"<>|\x00-\x1f]/g, '_') - .replace(/^\.+/, '') - .trim(); - return cleaned || 'unnamed'; -} - function uniquePathFor(fs, path, dir, filename) { const safeFilename = sanitizeFilename(filename); const parsed = path.parse(safeFilename); @@ -342,7 +330,6 @@ module.exports = registerExportCommand; module.exports.EXPORT_MARKER = EXPORT_MARKER; module.exports.writeExportMarker = writeExportMarker; module.exports.isExportDirectory = isExportDirectory; -module.exports.sanitizeFilename = sanitizeFilename; module.exports.uniquePathFor = uniquePathFor; module.exports.writeStream = writeStream; module.exports.sanitizeTitle = sanitizeTitle; diff --git a/lib/file-utils.js b/lib/file-utils.js new file mode 100644 index 0000000..84e8762 --- /dev/null +++ b/lib/file-utils.js @@ -0,0 +1,16 @@ +const path = require('path'); + +function sanitizeFilename(filename) { + if (!filename || typeof filename !== 'string') { + return 'unnamed'; + } + const stripped = path.basename(filename.replace(/\\/g, '/')); + const cleaned = stripped + // eslint-disable-next-line no-control-regex + .replace(/[\\/:*?"<>|\x00-\x1f]/g, '_') + .replace(/^\.+/, '') + .trim(); + return cleaned || 'unnamed'; +} + +module.exports = { sanitizeFilename }; diff --git a/tests/export.test.js b/tests/export.test.js index 189eee5..68e275c 100644 --- a/tests/export.test.js +++ b/tests/export.test.js @@ -7,8 +7,8 @@ const { uniquePathFor, exportRecursive, sanitizeTitle, - sanitizeFilename, } = require('../bin/commands/export.js'); +const { sanitizeFilename } = require('../lib/file-utils'); // --------------------------------------------------------------------------- // Helpers: in-memory fs mock