Created
August 18, 2017 02:21
-
-
Save chjj/bd026c503add3c5387e798cf24eaa3b1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const path = require('path'); | |
const fs = require('./lib/utils/fs'); | |
async function findFiles(dir, match, ignore, files) { | |
const list = await fs.readdir(dir); | |
for (const name of list) { | |
if (ignore.has(name)) | |
continue; | |
const file = path.join(dir, name); | |
const stat = await fs.lstat(file); | |
if (stat.isSymbolicLink()) | |
continue; | |
if (stat.isDirectory()) { | |
await findFiles(file, match, ignore, files); | |
continue; | |
} | |
if (!match.test(name)) | |
continue; | |
files.push(file); | |
} | |
return files; | |
} | |
async function getFiles(dir, ignore, match) { | |
const set = new Set(); | |
if (!ignore) | |
ignore = []; | |
for (const name of ignore) | |
set.add(name); | |
if (!match) | |
match = /^[^\0]+\.js$/; | |
return await findFiles(dir, match, set, []); | |
} | |
function indentLines(text, spaces) { | |
const spacing = Array(spaces + 1).join(' '); | |
const lines = text.split('\n'); | |
const indent = []; | |
for (let line of lines) { | |
if (line.length !== 0) | |
line = spacing + line; | |
indent.push(line); | |
} | |
return indent.join('\n'); | |
} | |
function processFile(data) { | |
let mod = false; | |
const fnToClass = | |
/\n(\/\*\*(?:\n \*[^\n]*)+?\n \*\/\s+)?function ([A-Z]\w*)\(([^)]*)\) \{([^\0]+?\n)\};?(?:\s*Object\.setPrototypeOf\([^,]+, ([^.]+)\.prototype\);\n)?/g; | |
data = data.replace(fnToClass, (_, comment, name, args, body, parent) => { | |
mod = true; | |
if (!comment) | |
comment = ''; | |
if (!parent) | |
parent = ''; | |
comment = indentLines(comment, 1); | |
body = indentLines(body, 1); | |
if (parent) | |
parent = ` extends ${parent}`; | |
return `\nclass ${name}${parent} {\n${comment} constructor(${args}) {${body} }\n}`; | |
}); | |
const methodToClass = | |
/\n(\/\*\*(?:\n \*[^\n]*)+?\n \*\/\s+)?[A-Z]\w*(\.prototype)?\.\w+ = (async |)function ([^{]+)\{([^\0]*?\n)\};/g; | |
data = data.replace(methodToClass, (_, comment, proto, asyn, nameargs, body) => { | |
mod = true; | |
if (!comment) | |
comment = ''; | |
comment = indentLines(comment, 1); | |
body = indentLines(body, 1); | |
let stat = ''; | |
if (!proto) | |
stat = 'static '; | |
return `\n${comment} ${stat}${asyn}${nameargs}{${body} }`; | |
}); | |
const ctorToSuper = /[A-Z]\w*\.call\(this(?:, ([^)]+))?\);/g; | |
data = data.replace(ctorToSuper, (_, args) => { | |
mod = true; | |
if (!args) | |
args = ''; | |
return `super(${args});`; | |
}); | |
const wrapper = | |
/\n *if \(!\(this instanceof ([A-Z]\w*)\)\)\n *return new \1[^\n]+\n/g; | |
data = data.replace(wrapper, () => { | |
mod = true; | |
return ''; | |
}); | |
if (!mod) | |
return null; | |
return data; | |
} | |
async function rewriteFile(filename) { | |
let data = await fs.readFile(filename, 'utf8'); | |
data = processFile(data); | |
if (data === null) | |
return; | |
await fs.writeFile(filename, data); | |
} | |
async function rewriteFiles(files) { | |
const jobs = files.map(file => rewriteFile(file)); | |
return await Promise.all(jobs); | |
} | |
(async () => { | |
const target = process.argv[2] || '.'; | |
const cwd = path.resolve(process.cwd(), target); | |
const ignore = ['node_modules', 'vendor']; | |
const files = await getFiles(cwd, ignore); | |
await rewriteFiles(files); | |
})().catch((err) => { | |
console.error(err.stack); | |
process.exit(1); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment