js-refactor
Advanced tools
Comparing version 1.0.4 to 1.0.5
@@ -20,26 +20,40 @@ #! /usr/bin/env node | ||
const srcRoot = process.cwd(); | ||
const args = process.argv; | ||
const subdirOld = args[2]; | ||
const subdirNew = args[3]; | ||
const srcRoot = process.cwd(); | ||
const fromFile = (0, _utils.toAbsolute)(args[2], srcRoot); | ||
const toFile = (0, _utils.toAbsolute)(args[3], srcRoot); | ||
function help() { | ||
console.error('Usage: js-refactor <from-directory> <to-directory>'); | ||
} | ||
if (_fs2.default.existsSync(subdirNew)) { | ||
const stat = _fs2.default.statSync(fromFile); | ||
if (!stat) { | ||
help(); | ||
throw new Error(`subdirNew exists: ${subdirNew}`); | ||
throw new Error(`fromFile does not exists: ${fromFile}`); | ||
} | ||
if (!_fs2.default.existsSync(subdirOld)) { | ||
if (_fs2.default.existsSync(toFile)) { | ||
help(); | ||
throw new Error(`subdirOld does not exists: ${subdirOld}`); | ||
throw new Error(`toFile already exists: ${toFile}`); | ||
} | ||
_fs2.default.renameSync(subdirOld, subdirNew); | ||
_fs2.default.renameSync(fromFile, toFile); | ||
const MATCH_REQUIRE = /require\(['"](.+?)['"]\)/g; | ||
const MATCH_IMPORT = /import .+? from ['"](.+?)['"]/g; | ||
const isDirectory = stat.isDirectory(fromFile); | ||
const subdirOld = isDirectory && fromFile; | ||
const subdirNew = isDirectory && toFile; | ||
function help() { | ||
console.error('Usage: js-refactor <from-file> <to-file>'); | ||
} | ||
const MATCH_REQUIRE = /require\s*\(\s*['"]([\s\S]+?)['"]\s*\)/g; | ||
const MATCH_IMPORT = /import[\s\S]+?from\s*['"](.+?)['"]/g; | ||
const MATCH_EXPORT = /export[\s\S]+?from\s*['"](.+?)['"]/g; | ||
const IGNORE_DIR = /\/node_modules\/?$/; | ||
const SELECT_SOURCE_FILE = /\.js$/; | ||
function addSuffix(dep) { | ||
return dep + '.js'; | ||
} | ||
function trimSuffix(dep) { | ||
return dep.replace(/\.js$/, ''); | ||
} | ||
function shouldFix(file) { | ||
@@ -83,16 +97,49 @@ return (/^src\/|^\.\/|^\.\.\//.test(file) | ||
// fix files within subdir | ||
console.log('processing internal files\n\n'); | ||
iterateSourceFiles(subdirNew, { excludes: [IGNORE_DIR] }, ({ file }) => { | ||
const dir = _path2.default.dirname(file); | ||
const wouldBePath = _path2.default.join(subdirOld, _path2.default.relative(subdirNew, file)); | ||
const wouldBeDir = _path2.default.dirname(wouldBePath); | ||
const fileContent = _fs2.default.readFileSync(file, { encoding: 'utf8' }); | ||
const lines = fileContent.split('\n'); | ||
function fixOnlyFile() { | ||
console.log('fix only file\n\n'); | ||
let fileContent = _fs2.default.readFileSync(toFile, { encoding: 'utf8' }); | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach(re => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
// 其他模块/文件/包,忽略 | ||
if (!shouldFix(dep)) { | ||
continue; | ||
} | ||
const isRela = (0, _utils.isRelative)(dep); | ||
if (!isRela) { | ||
continue; | ||
} | ||
const dirOld = _path2.default.dirname(fromFile); | ||
const dirNew = _path2.default.dirname(toFile); | ||
if ((0, _utils.isSameFile)(dirOld, dirNew)) { | ||
return; | ||
} | ||
const realDep = _path2.default.join(dirOld, dep); | ||
const newDep = _path2.default.relative(dirNew, realDep); | ||
if (isRela && !(0, _utils.isRelative)(newDep)) { | ||
newDep = './' + newDep; | ||
} | ||
lines.forEach((line, ii) => { | ||
[MATCH_IMPORT, MATCH_REQUIRE].forEach(re => { | ||
console.log('update file: %s\n %s\n->%s\n', toFile, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
_fs2.default.writeFileSync(toFile, fileContent); | ||
} | ||
function fixFilesDependingOnOnlyFile() { | ||
console.log('fix files depending on only file\n\n'); | ||
iterateSourceFiles(srcRoot, { excludes: [IGNORE_DIR] }, ({ file }) => { | ||
if ((0, _utils.isSameFile)(file, toFile)) { | ||
return; | ||
} | ||
const dir = _path2.default.dirname(file); | ||
let fileContent = _fs2.default.readFileSync(file, { encoding: 'utf8' }); | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach(re => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(line)) !== null) { | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
@@ -104,2 +151,40 @@ // 其他模块/文件/包,忽略 | ||
const isRela = (0, _utils.isRelative)(dep); | ||
const realDep = _path2.default.join(dir, dep); | ||
if (!(0, _utils.isSameFile)(addSuffix(realDep), fromFile)) { | ||
continue; | ||
} | ||
if (/WebView/.test(dep)) { | ||
console.log('realDep, toFile, isRela, dep', realDep, toFile, isRela, dep); | ||
} | ||
const newDep = _path2.default.relative(dir, trimSuffix(toFile)); | ||
if (isRela && !(0, _utils.isRelative)(newDep)) { | ||
newDep = './' + newDep; | ||
} | ||
console.log('update file: %s\n %s\n->%s\n', file, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
_fs2.default.writeFileSync(file, fileContent); | ||
}); | ||
} | ||
// fix files within subdir | ||
function fixFilesInSubdir() { | ||
console.log('processing internal files\n\n'); | ||
iterateSourceFiles(subdirNew, { excludes: [IGNORE_DIR] }, ({ file }) => { | ||
const dir = _path2.default.dirname(file); | ||
const wouldBePath = _path2.default.join(subdirOld, _path2.default.relative(subdirNew, file)); | ||
const wouldBeDir = _path2.default.dirname(wouldBePath); | ||
let fileContent = _fs2.default.readFileSync(file, { encoding: 'utf8' }); | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach(re => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
// 其他模块/文件/包,忽略 | ||
if (!shouldFix(dep)) { | ||
continue; | ||
} | ||
const isRela = (0, _utils.isRelative)(dep); | ||
const wouldBeDep = isRelativeToSrcRoot(dep) ? _path2.default.join(srcRoot, dep) : _path2.default.join(wouldBeDir, dep); | ||
@@ -117,24 +202,23 @@ const isInnerFile = (0, _utils.isSuperDir)(subdirOld, wouldBeDep); | ||
const newline = line.substr(0, m.index) + line.substr(m.index).replace(dep, newDep); | ||
console.log('update file: %s\n %s\n->%s\n', file, line, newline); | ||
lines[ii] = newline; | ||
console.log('update file: %s\n %s\n->%s\n', file, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
_fs2.default.writeFileSync(file, fileContent); | ||
}); | ||
_fs2.default.writeFileSync(file, lines.join('\n')); | ||
}); | ||
} | ||
// fix files outside subdir | ||
console.log('processing external files\n\n'); | ||
iterateSourceFiles(srcRoot, { excludes: [d => (0, _utils.isSuperDir)(subdirNew, d), IGNORE_DIR] }, ({ file }) => { | ||
function fixFilesOutsideSubdir() { | ||
console.log('processing external files\n\n'); | ||
iterateSourceFiles(srcRoot, { excludes: [d => (0, _utils.isSuperDir)(subdirNew, d), IGNORE_DIR] }, ({ file }) => { | ||
const dir = _path2.default.dirname(file); | ||
const fileContent = _fs2.default.readFileSync(file, { encoding: 'utf8' }); | ||
const lines = fileContent.split('\n'); | ||
const dir = _path2.default.dirname(file); | ||
let fileContent = _fs2.default.readFileSync(file, { encoding: 'utf8' }); | ||
lines.forEach((line, ii) => { | ||
[MATCH_IMPORT, MATCH_REQUIRE].forEach(re => { | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach(re => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(line)) !== null) { | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
@@ -147,3 +231,3 @@ // 其他模块/文件/包,忽略 | ||
const oldDepPath = isRelativeToSrcRoot(dep) ? _path2.default.join(srcRoot, dep) : _path2.default.join(dir, dep); | ||
const isAffected = (0, _utils.isSuperDir)(_path2.default.join(srcRoot, subdirOld), oldDepPath); | ||
const isAffected = (0, _utils.isSuperDir)(subdirOld, oldDepPath); | ||
if (!isAffected) { | ||
@@ -157,9 +241,17 @@ continue; | ||
} | ||
const newline = line.substr(0, m.index) + line.substr(m.index).replace(dep, newDep); | ||
console.log('update file: %s\n %s\n->%s\n', file, line, newline); | ||
lines[ii] = newline; | ||
console.log('update file: %s\n %s\n->%s\n', file, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
_fs2.default.writeFileSync(file, fileContent); | ||
}); | ||
_fs2.default.writeFileSync(file, lines.join('\n')); | ||
}); | ||
} | ||
if (isDirectory) { | ||
fixFilesInSubdir(); | ||
fixFilesOutsideSubdir(); | ||
} else { | ||
fixOnlyFile(); | ||
fixFilesDependingOnOnlyFile(); | ||
} |
@@ -8,2 +8,4 @@ 'use strict'; | ||
exports.isSuperDir = isSuperDir; | ||
exports.toAbsolute = toAbsolute; | ||
exports.isSameFile = isSameFile; | ||
@@ -35,2 +37,13 @@ var _path = require('path'); | ||
return addTrailingSlash(childDir).startsWith(addTrailingSlash(superDir)); | ||
} | ||
function toAbsolute(f, b) { | ||
if (_path2.default.isAbsolute(f)) { | ||
return f; | ||
} | ||
return _path2.default.join(b, f); | ||
} | ||
function isSameFile(f1, f2) { | ||
return _path2.default.normalize(f1) === _path2.default.normalize(f2); | ||
} |
{ | ||
"name": "js-refactor", | ||
"version": "1.0.4", | ||
"version": "1.0.5", | ||
"description": "mv file/directory around keeping require and import statements in sync", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
190
src/index.js
@@ -5,29 +5,46 @@ #! /usr/bin/env node | ||
import traverser from 'directory-traverser'; | ||
import { isRelative, isSuperDir } from './utils'; | ||
import { isRelative, isSuperDir, toAbsolute, isSameFile } from './utils'; | ||
const srcRoot = process.cwd(); | ||
const args = process.argv; | ||
const subdirOld = args[2]; | ||
const subdirNew = args[3]; | ||
const srcRoot = process.cwd(); | ||
const fromFile = toAbsolute(args[2], srcRoot); | ||
const toFile = toAbsolute(args[3], srcRoot); | ||
function help() { | ||
console.error('Usage: js-refactor <from-directory> <to-directory>'); | ||
} | ||
if (fs.existsSync(subdirNew)) { | ||
const stat = fs.statSync(fromFile); | ||
if (!stat) { | ||
help(); | ||
throw new Error(`subdirNew exists: ${subdirNew}`); | ||
throw new Error(`fromFile does not exists: ${fromFile}`); | ||
} | ||
if (!fs.existsSync(subdirOld)) { | ||
if (fs.existsSync(toFile)) { | ||
help(); | ||
throw new Error(`subdirOld does not exists: ${subdirOld}`); | ||
throw new Error(`toFile already exists: ${toFile}`); | ||
} | ||
fs.renameSync(subdirOld, subdirNew); | ||
fs.renameSync(fromFile, toFile); | ||
const isDirectory = stat.isDirectory(fromFile); | ||
const subdirOld = isDirectory && fromFile; | ||
const subdirNew = isDirectory && toFile; | ||
const MATCH_REQUIRE = /require\(['"](.+?)['"]\)/g; | ||
const MATCH_IMPORT = /import .+? from ['"](.+?)['"]/g; | ||
function help() { | ||
console.error('Usage: js-refactor <from-file> <to-file>'); | ||
} | ||
const MATCH_REQUIRE = /require\s*\(\s*['"]([\s\S]+?)['"]\s*\)/g; | ||
const MATCH_IMPORT = /import[\s\S]+?from\s*['"](.+?)['"]/g; | ||
const MATCH_EXPORT = /export[\s\S]+?from\s*['"](.+?)['"]/g; | ||
const IGNORE_DIR = /\/node_modules\/?$/; | ||
const SELECT_SOURCE_FILE = /\.js$/; | ||
function addSuffix(dep) { | ||
return dep + '.js'; | ||
} | ||
function trimSuffix(dep) { | ||
return dep.replace(/\.js$/, ''); | ||
} | ||
function shouldFix(file) { | ||
@@ -69,16 +86,53 @@ return /^src\/|^\.\/|^\.\.\//.test(file); | ||
// fix files within subdir | ||
console.log('processing internal files\n\n'); | ||
iterateSourceFiles(subdirNew, { excludes: [IGNORE_DIR] }, ({ file }) => { | ||
const dir = path.dirname(file); | ||
const wouldBePath = path.join(subdirOld, path.relative(subdirNew, file)); | ||
const wouldBeDir = path.dirname(wouldBePath); | ||
const fileContent = fs.readFileSync(file, { encoding: 'utf8' }); | ||
const lines = fileContent.split('\n'); | ||
lines.forEach((line, ii) => { | ||
[MATCH_IMPORT, MATCH_REQUIRE].forEach((re) => { | ||
function fixOnlyFile() { | ||
console.log('fix only file\n\n'); | ||
let fileContent = fs.readFileSync(toFile, { encoding: 'utf8' }); | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach((re) => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
// 其他模块/文件/包,忽略 | ||
if (!shouldFix(dep)) { | ||
continue; | ||
} | ||
const isRela = isRelative(dep); | ||
if (!isRela) { | ||
continue; | ||
} | ||
const dirOld = path.dirname(fromFile); | ||
const dirNew = path.dirname(toFile); | ||
if (isSameFile(dirOld, dirNew)) { | ||
return; | ||
} | ||
const realDep = path.join(dirOld, dep); | ||
const newDep = path.relative(dirNew, realDep); | ||
if (isRela && !isRelative(newDep)) { | ||
newDep = './' + newDep; | ||
} | ||
console.log('update file: %s\n %s\n->%s\n', toFile, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
fs.writeFileSync(toFile, fileContent); | ||
} | ||
function fixFilesDependingOnOnlyFile() { | ||
console.log('fix files depending on only file\n\n'); | ||
iterateSourceFiles(srcRoot, | ||
{ excludes: [IGNORE_DIR] }, | ||
({ file }) => { | ||
if (isSameFile(file, toFile)) { | ||
return; | ||
} | ||
const dir = path.dirname(file); | ||
let fileContent = fs.readFileSync(file, { encoding: 'utf8' }); | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach((re) => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(line)) !== null) { | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
@@ -90,2 +144,38 @@ // 其他模块/文件/包,忽略 | ||
const isRela = isRelative(dep); | ||
const realDep = path.join(dir, dep); | ||
if (!isSameFile(addSuffix(realDep), fromFile)) { | ||
continue; | ||
} | ||
const newDep = path.relative(dir, trimSuffix(toFile)); | ||
if (isRela && !isRelative(newDep)) { | ||
newDep = './' + newDep; | ||
} | ||
console.log('update file: %s\n %s\n->%s\n', file, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
fs.writeFileSync(file, fileContent); | ||
}); | ||
} | ||
// fix files within subdir | ||
function fixFilesInSubdir() { | ||
console.log('processing internal files\n\n'); | ||
iterateSourceFiles(subdirNew, { excludes: [IGNORE_DIR] }, ({ file }) => { | ||
const dir = path.dirname(file); | ||
const wouldBePath = path.join(subdirOld, path.relative(subdirNew, file)); | ||
const wouldBeDir = path.dirname(wouldBePath); | ||
let fileContent = fs.readFileSync(file, { encoding: 'utf8' }); | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach((re) => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
// 其他模块/文件/包,忽略 | ||
if (!shouldFix(dep)) { | ||
continue; | ||
} | ||
const isRela = isRelative(dep); | ||
const wouldBeDep = isRelativeToSrcRoot(dep) ? | ||
@@ -106,27 +196,26 @@ path.join(srcRoot, dep) : path.join(wouldBeDir, dep); | ||
const newline = line.substr(0, m.index) + line.substr(m.index).replace(dep, newDep); | ||
console.log('update file: %s\n %s\n->%s\n', file, line, newline); | ||
lines[ii] = newline; | ||
console.log('update file: %s\n %s\n->%s\n', file, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
fs.writeFileSync(file, fileContent); | ||
}); | ||
fs.writeFileSync(file, lines.join('\n')); | ||
}); | ||
} | ||
// fix files outside subdir | ||
console.log('processing external files\n\n'); | ||
iterateSourceFiles(srcRoot, | ||
{ excludes: [d => isSuperDir(subdirNew, d), IGNORE_DIR] }, | ||
({ file }) => { | ||
function fixFilesOutsideSubdir() { | ||
console.log('processing external files\n\n'); | ||
iterateSourceFiles(srcRoot, | ||
{ excludes: [d => isSuperDir(subdirNew, d), IGNORE_DIR] }, | ||
({ file }) => { | ||
const dir = path.dirname(file); | ||
const fileContent = fs.readFileSync(file, { encoding: 'utf8' }); | ||
const lines = fileContent.split('\n'); | ||
const dir = path.dirname(file); | ||
let fileContent = fs.readFileSync(file, { encoding: 'utf8' }); | ||
lines.forEach((line, ii) => { | ||
[MATCH_IMPORT, MATCH_REQUIRE].forEach((re) => { | ||
[MATCH_IMPORT, MATCH_REQUIRE, MATCH_EXPORT].forEach((re) => { | ||
re.lastIndex = 0; | ||
let m; | ||
while ((m = re.exec(line)) !== null) { | ||
while ((m = re.exec(fileContent)) !== null) { | ||
const dep = m[1]; | ||
@@ -140,3 +229,3 @@ // 其他模块/文件/包,忽略 | ||
path.join(srcRoot, dep) : path.join(dir, dep); | ||
const isAffected = isSuperDir(path.join(srcRoot, subdirOld), oldDepPath); | ||
const isAffected = isSuperDir(subdirOld, oldDepPath); | ||
if (!isAffected) { | ||
@@ -151,10 +240,17 @@ continue; | ||
} | ||
const newline = line.substr(0, m.index) + | ||
line.substr(m.index).replace(dep, newDep); | ||
console.log('update file: %s\n %s\n->%s\n', file, line, newline); | ||
lines[ii] = newline; | ||
console.log('update file: %s\n %s\n->%s\n', file, dep, newDep); | ||
fileContent = fileContent.substr(0, m.index) + fileContent.substr(m.index).replace(dep, newDep); | ||
re.lastIndex += newDep.length - dep.length; | ||
} | ||
}); | ||
fs.writeFileSync(file, fileContent); | ||
}); | ||
fs.writeFileSync(file, lines.join('\n')); | ||
}); | ||
} | ||
if (isDirectory) { | ||
fixFilesInSubdir(); | ||
fixFilesOutsideSubdir(); | ||
} else { | ||
fixOnlyFile(); | ||
fixFilesDependingOnOnlyFile(); | ||
} |
@@ -20,1 +20,12 @@ import path from 'path'; | ||
} | ||
export function toAbsolute(f, b) { | ||
if (path.isAbsolute(f)) { | ||
return f; | ||
} | ||
return path.join(b, f); | ||
} | ||
export function isSameFile(f1, f2) { | ||
return path.normalize(f1) === path.normalize(f2); | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
77501
504