Created
November 28, 2016 17:22
-
-
Save DanielKoehler/a94134fd8afe557b702e443026cd3f08 to your computer and use it in GitHub Desktop.
A really horrible (but functioning) script that will try to convert ES6 style imports in a project to require() style syntax.
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
| import re | |
| from os import path | |
| import click | |
| import json | |
| importExpression = r""".*import[ \t]+(?P<varname>[a-zA-Z0-9*_ ]+,*\s*)*({\s*(?P<module>[a-zA-Z0-9_*\s,]+)*\s*})*[ \t]+from[ \t]+(?P<br>['"])(?P<path>[a-zA-Z0-9-_\.\/]+)(?P=br).*""" | |
| def lookahead(iterable): | |
| # Get an iterator and pull the first value. | |
| it = iter(iterable) | |
| last = next(it) | |
| # Run the iterator to exhaustion (starting from the second value). | |
| for val in it: | |
| # Report the *previous* value (more to come). | |
| yield last, True | |
| last = val | |
| # Report the last value. | |
| yield last, False | |
| def require_from_module_default(direct_import_string, destructured_import_string, path): | |
| direct = [] | |
| destructured = [] | |
| suffixed = [] | |
| definition= [] | |
| if direct_import_string: | |
| direct_imports = direct_import_string.strip().split(",") | |
| [direct.append(direct_import) for direct_import in direct_imports if len(direct_import)] | |
| # print "require_from_module_default", direct, len(direct) | |
| for i, _import in enumerate(direct[:]): | |
| if " as " in _import: | |
| (packaged_name,local_name) = _import.split(" as ") | |
| if packaged_name.strip() in ["default", "*"]: # this is just the same as var local_name = require('package') | |
| direct[i] = local_name | |
| else: | |
| # print "here!!" | |
| raise ValueError(_import + " in " + __file__) | |
| # suffixed.append((packaged_name,local_name)) | |
| else: | |
| # direct[i] = _import == direct[i] | |
| pass | |
| # import *{ named, ... }* from 'package' | |
| if destructured_import_string: | |
| destructured_imports = [x.strip() for x in destructured_import_string.split(",")] | |
| # import { named *as* othername, ... } from 'package' | |
| for _import in destructured_imports: | |
| if " as " in _import: | |
| (packaged_name,local_name) = _import.split(" as ") | |
| if packaged_name.strip() == "default": # this is just the same as var local_name = require('package') | |
| direct.append(local_name) | |
| else: | |
| suffixed.append((packaged_name,local_name)) | |
| else: | |
| destructured.append(_import) | |
| if len(direct) == 1: | |
| definition.append("var {definition} = require('{path}')".format(definition=direct[0], path=path)) | |
| if len(destructured): | |
| if len(direct) < 1: | |
| imported = "require('{path}')".format(path=path) | |
| else: | |
| imported = direct[0] | |
| definition.append("var {{ {module} }} = {imported}".format(imported = imported, module=", ".join(destructured))) | |
| # e.g. : import { reducer as formReducer } from 'redux-form' | |
| # : var formReducer = require('redux-form').reducer | |
| if len(suffixed): | |
| if len(direct) < 1: | |
| imported = "require('{path}')".format(path=path) | |
| else: | |
| imported = direct[0] | |
| for (packaged_name,local_name) in suffixed: | |
| definition.append("\tvar {local_name} = {imported}.{packedname}".format(local_name=local_name,imported = imported, packedname=packaged_name)) | |
| if len(direct) > 1: | |
| raise ValueError("Not really sure how to handle more than 1 top level import: %s" % direct ) | |
| return "\n".join(definition) | |
| explored = {} | |
| local_packages = [] | |
| def fix_imports(lines, filename): | |
| compiledImportRE = re.compile(importExpression, 0) | |
| for index, line in enumerate(lines): | |
| if "import" in line: | |
| # print line | |
| result = compiledImportRE.match(line) | |
| if result is not None: | |
| # print "line" | |
| data = result.groupdict() | |
| # print "data", data | |
| if data['module'] or data['varname']: | |
| output = require_from_module_default( data['varname'], data['module'] , data['path']) | |
| # print "after data" | |
| # Found a local package | |
| if data['path'].startswith("."): | |
| local_package = path.realpath(path.join(path.dirname(filename), data['path'] )) | |
| if local_package not in explored: | |
| local_packages.append(local_package) | |
| lines[index] = output | |
| # print line.rjust(70, ' '), " ===> ", output | |
| output = "" | |
| # | |
| # with open(filename, 'w') as file: | |
| # file.writelines( ["%s\n" % line for line in lines ] ) | |
| def fix_exports(lines, filename): | |
| module_default = None | |
| module_exports = [] | |
| exportWord = re.compile(r"export\s+([a-zA-Z]+)\s+", 0) | |
| exportDefault = re.compile(r"export\s+default", 0) | |
| delimit = { | |
| 'const' : '=', | |
| 'function' : '(', | |
| 'class' : '{', | |
| 'var' : '=' | |
| } | |
| for line_index, line in enumerate(lines): | |
| if "export" in line: | |
| match = exportDefault.match(line) | |
| output = line.replace("export", "").strip() | |
| # print "testing: %s" % line | |
| if match: # DEFAULT | |
| module_default = {'value': output.replace("default", "").split(" = ")[0].strip(), 'line': line_index} | |
| else: | |
| match = exportWord.match(line) | |
| output = line.replace("export", "").strip() | |
| # print "here" | |
| if match: # CONST | |
| # print "exportWord = match" | |
| _type = output.split(" ")[0] | |
| out = output.replace(_type, "").split(delimit[_type])[0].strip() | |
| if _type == "class": | |
| out = out.split(" ")[0] | |
| # print line | |
| # print _type, "---->", out | |
| # print output, line_index | |
| lines[line_index] = output | |
| module_exports.append( | |
| { | |
| "external":out, | |
| "local":out | |
| }) | |
| # print lines | |
| if len(module_exports) and module_default: | |
| # print "FAIL", module_exports, module_default | |
| lines[module_default['line']] = "module.exports = {}".format(module_default['value']) | |
| for me in module_exports: | |
| lines.append("module.exports.{external} = {local}".format(external=me['external'], local=me['local'])) | |
| # module.exports.notificationReducer = notificationReducer | |
| else: | |
| if module_default: | |
| lines[module_default['line']] = "module.exports = {}".format(module_default['value']) | |
| elif len(module_exports): | |
| lines.append("\nmodule.exports = {") | |
| for me, has_more in lookahead(module_exports): | |
| lines.append(" {external}: {local}".format(external=me['external'], local=me['local'])) | |
| if has_more: | |
| lines[-1] = lines[-1] + "," | |
| lines.append("}") | |
| with open(filename, 'w') as file: | |
| file.writelines( ["%s\n" % line for line in lines ] ) | |
| # print "PASSING" | |
| def parse(input_filename): | |
| filename = input_filename | |
| if filename in explored: | |
| # (click.style("Circular import to {filename} - ignoring".format(filename=filename), bg='white', fg='red')) | |
| return | |
| possible_extensions = ['.jsx', '.js'] | |
| if not path.isfile(filename): | |
| for ext in possible_extensions: | |
| if path.isfile(filename + ext): | |
| filename += ext | |
| if path.isdir(filename): | |
| print "Didn't process:", filename | |
| return | |
| with open(filename) as f: | |
| lines = [line.rstrip('\n') for line in f] | |
| click.echo(click.style('Parsing: ' + filename, bg='blue', fg='white')) | |
| fix_imports(lines, filename) | |
| fix_exports(lines, filename) | |
| if input_filename not in explored: | |
| explored[input_filename] = True | |
| return | |
| # def parse(input_filename): | |
| @click.command() | |
| @click.argument('f', type=click.Path(exists=True)) | |
| def six_to_five(f): | |
| """Doc """ | |
| abspath = path.realpath(path.join(path.dirname( __file__ ), f)) | |
| parse(abspath) | |
| while len(local_packages) > 0: | |
| parse(local_packages.pop(0)) | |
| click.echo(click.style('Total files explored: {}'.format(len(explored.keys())), fg='green')) | |
| if __name__ == '__main__': | |
| six_to_five() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Imports
e.g.
Becomes:
Exports
e.g.
Becomes