#!/usr/bin/python
from optparse import OptionParser
import os
import re
import sys
def extract_require(s):
m = re.search('(//)?(.*)require\\("(.*)"\\)', s)
if not m or m.group(1):
return None
prefix = m.group(2)
if prefix and len(prefix):
prefix = prefix[-1]
if prefix.isalpha() or prefix.isdigit() or prefix == '_':
return None
return m.group(3)
def resolve_path(file, dirs):
if os.path.isabs(file):
return file
for d in dirs:
result = os.path.join(d, file)
if os.path.exists(result):
return result
raise Exception('cannot find "%s" in "%s"' % (file, dirs))
def process(path, out, resolved, resolving, dirs):
module_name = os.path.splitext(os.path.basename(path))[0]
if module_name in resolving:
raise Exception('cyclic import detected: "%s"' % module_name)
result = 'imports["%s"] = {};\n' % path
result += '(function module$%s(exports){\n' % module_name
src_path = resolve_path(path, dirs)
with open(src_path) as f:
for l in f:
req = extract_require(l)
if req and not req in resolved:
try:
process(req, out, resolved, resolving + [module_name], dirs)
except Exception:
print('while resolving "%s"...' % module_name)
raise sys.exc_info()[1]
result += l
result += '\n})(imports["%s"]);\n' % path
out.write(result)
resolved += [path]
def encode_to_js_string(s):
escape = [('\n', '\\n'), ('\r', '\\r'), ('"', '""')]
for e in escape:
s = s.replace(e[0], e[1])
return '"%s"' % s
def link(input_paths, output_path, dirs, version = None):
with open(output_path, "w") as out:
prolog = ""
if not version is None:
prolog += 'var buildVersion = %s;\n' % encode_to_js_string(version)
prolog += "var GLOBAL = this;\n"
prolog += "var imports = {};\n"
prolog += 'function require(module){return imports[module];}\n'
out.write(prolog)
resolved = []
resolving = []
for input_path in input_paths:
process(input_path, out, resolved, resolving, dirs)
def parse_args(args):
parser = OptionParser('Usage: linkjs.py [options]