25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bundle.py 3.4 KiB

14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
14 년 전
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. from minify import JavascriptMinify
  2. class Bundle:
  3. """
  4. Concatenate, compress and mix (if required) js+css files from build.json
  5. """
  6. def concat(self, filelist, outfile=None, is_js=False):
  7. """
  8. Concat css and js files into a bundle
  9. """
  10. import os
  11. from cStringIO import StringIO
  12. from build import verbose
  13. out_type = outfile and outfile.split('.')[-1] or 'js'
  14. temp = StringIO()
  15. for f in filelist:
  16. if verbose:
  17. print f + ' | ' + str(int(os.path.getsize(f)/1024)) + 'k'
  18. fh = open(f)
  19. # get file type
  20. ftype = f.split('.')[-1]
  21. # special concat (css inside js)
  22. if is_js and ftype =='css':
  23. css = fh.read()
  24. data = "\nwn.assets.handler.css('%s');\n" % css.replace("'", "\\'").replace('\n', '\\\n')
  25. # plain concat
  26. else:
  27. data = fh.read() + '\n'
  28. fh.close()
  29. temp.write(data)
  30. if outfile:
  31. f = open(outfile, 'w')
  32. f.write(temp.getvalue())
  33. f.close()
  34. self.vc.repo.add(outfile)
  35. if verbose: print 'Wrote %s' % outfile
  36. return temp
  37. def changed(self, files):
  38. """
  39. Returns true if the files are changed since last build
  40. """
  41. import os
  42. from build import force_rebuild, verbose
  43. if force_rebuild:
  44. return True
  45. for f in files:
  46. if f in self.dirty:
  47. if verbose:
  48. print '*** %s changed' % f
  49. return True
  50. return False
  51. def minify(self, in_files, outfile, concat=False):
  52. """
  53. Compress in_files into outfile,
  54. give some stats
  55. """
  56. from build import verbose
  57. import os
  58. # concat everything into temp
  59. outtype = outfile.split('.')[-1]
  60. temp = self.concat(in_files, is_js=True)
  61. out = open(outfile, 'w')
  62. org_size = len(temp.getvalue())
  63. temp.seek(0)
  64. # minify
  65. jsm = JavascriptMinify()
  66. jsm.minify(temp, out)
  67. out.close()
  68. self.vc.repo.add(outfile)
  69. new_size = os.path.getsize(outfile)
  70. if verbose:
  71. print '=> %s' % outfile
  72. print 'Original: %.2f kB' % (org_size / 1024.0)
  73. print 'Compressed: %.2f kB' % (new_size / 1024.0)
  74. print 'Reduction: %.1f%%' % (float(org_size - new_size) / org_size * 100)
  75. def make(self, bpath):
  76. """
  77. Build (stitch + compress) the file defined in build.json
  78. """
  79. import os, sys, json
  80. from build import no_minify
  81. # open the build.json file and read
  82. # the dict
  83. bfile = open(bpath, 'r')
  84. bdata = json.loads(bfile.read())
  85. bfile.close()
  86. path = os.path.dirname(bpath)
  87. for outfile in bdata:
  88. prefix, fname = False, outfile
  89. # check if there is a prefix
  90. if ':' in outfile:
  91. prefix, fname = outfile.split(':')
  92. # build the file list relative to the main folder
  93. fl = [os.path.relpath(os.path.join(path, f), os.curdir) for f in bdata[outfile]]
  94. if self.changed(fl):
  95. # js files are minified by default unless explicitly
  96. # mentioned in the prefix.
  97. # some files may not work if minified (known jsmin bug)
  98. if fname.split('.')[-1]=='js' and prefix!='concat' and not no_minify:
  99. self.minify(fl, os.path.relpath(os.path.join(path, fname), os.curdir))
  100. else:
  101. self.concat(fl, os.path.relpath(os.path.join(path, fname), os.curdir))
  102. def bundle(self, vc):
  103. """
  104. Build js files from "build.json" found in version control
  105. """
  106. import os
  107. self.dirty = vc.repo.uncommitted()
  108. self.vc = vc
  109. # walk the parent folder and build all files as defined in the build.json files
  110. for b in vc.repo.sql("select fname from bundles"):
  111. self.make(os.path.abspath(os.path.join(vc.root_path, b[0])))