linkjs.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #!/usr/bin/python
  2. import os
  3. import re
  4. import sys
  5. def extract_require(s):
  6. m = re.search('(//)?(.*)require\\("(.*)"\\)', s)
  7. if not m or m.group(1):
  8. return None
  9. prefix = m.group(2)
  10. if prefix and len(prefix):
  11. prefix = prefix[-1]
  12. if prefix.isalpha() or prefix.isdigit() or prefix == '_':
  13. return None
  14. return m.group(3)
  15. def resolve_require(req, out, resolved, resolving, dir):
  16. if not os.path.exists(os.path.join(dir, req)):
  17. raise Exception('cannot resolve "%s"' % req)
  18. process(req, out, resolved, resolving, dir)
  19. def process(path, out, resolved, resolving, dir):
  20. module_name = os.path.splitext(os.path.basename(path))[0]
  21. if module_name in resolving:
  22. raise Exception('cyclic import detected: "%s"' % module_name)
  23. result = 'imports["%s"] = {};\n' % path
  24. result += '(function %s(exports){\n' % module_name
  25. with open(os.path.join(dir, path)) as f:
  26. for l in f:
  27. req = extract_require(l)
  28. if req and not req in resolved:
  29. try:
  30. resolve_require(req, out, resolved, resolving + [module_name], dir)
  31. except Exception:
  32. print('while resolving "%s"...' % module_name)
  33. raise sys.exc_info()[1]
  34. result += l
  35. result += '\n})(imports["%s"]);\n' % path
  36. out.write(result)
  37. resolved += [path]
  38. def encode_to_js_string(s):
  39. escape = [('\n', '\\n'), ('\r', '\\r'), ('"', '""')]
  40. for e in escape:
  41. s = s.replace(e[0], e[1])
  42. return '"%s"' % s
  43. def link(input_path, output_path, dir, version = None):
  44. with open(output_path, "w") as out:
  45. prolog = ""
  46. if not version is None:
  47. prolog += 'var buildVersion = %s;\n' % encode_to_js_string(version)
  48. prolog += "var imports = {};\n"
  49. prolog += 'function require(module){return imports[module];}\n'
  50. out.write(prolog)
  51. process(input_path, out, [], [], dir)
  52. if __name__ == '__main__':
  53. if len(sys.argv) != 3:
  54. raise Exception("Usage: linkjs.py <input js> <output js>")
  55. link(sys.argv[1], sys.argv[2], '.')