Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

bundlejs.py 5.5 KiB

vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 12 Jahren
vor 14 Jahren
vor 12 Jahren
vor 12 Jahren
vor 13 Jahren
vor 12 Jahren
vor 14 Jahren
vor 12 Jahren
vor 14 Jahren
vor 13 Jahren
vor 14 Jahren
vor 13 Jahren
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. from __future__ import unicode_literals
  23. from webnotes.utils.minify import JavascriptMinify
  24. import os, sys
  25. class Bundle:
  26. """
  27. Concatenate, compress and mix (if required) js+css files from build.json
  28. """
  29. no_compress = False
  30. timestamps = {}
  31. path = '.'
  32. def concat(self, filelist, outfile=None):
  33. """
  34. Concat css and js files into a bundle
  35. """
  36. from cStringIO import StringIO
  37. out_type = outfile and outfile.split('.')[-1] or 'js'
  38. outtxt = ''
  39. for f in filelist:
  40. suffix = None
  41. if ':' in f:
  42. f, suffix = f.split(':')
  43. if not os.path.exists(f) or os.path.isdir(f):
  44. continue
  45. self.timestamps[f] = os.path.getmtime(f)
  46. # get datas
  47. with open(f, 'r') as infile:
  48. # get file type
  49. ftype = f.split('.')[-1]
  50. data = unicode(infile.read(), 'utf-8')
  51. outtxt += ('\n/*\n *\t%s\n */' % f)
  52. # append
  53. if suffix=='concat' or out_type != 'js' or self.no_compress or ('.min.' in f):
  54. outtxt += '\n' + data + '\n'
  55. else:
  56. jsm = JavascriptMinify()
  57. tmpin = StringIO(data.encode('utf-8'))
  58. tmpout = StringIO()
  59. jsm.minify(tmpin, tmpout)
  60. tmpmin = unicode(tmpout.getvalue() or '', 'utf-8')
  61. tmpmin.strip('\n')
  62. outtxt += tmpmin
  63. with open(outfile, 'w') as f:
  64. f.write(outtxt.encode("utf-8"))
  65. print "Wrote %s - %sk" % (outfile, str(int(os.path.getsize(outfile)/1024)))
  66. def dirty(self):
  67. """check if build files are dirty"""
  68. self.make_build_data()
  69. for builddict in self.bdata:
  70. for f in self.get_infiles(builddict):
  71. if ':' in f:
  72. f, suffix = f.split(':')
  73. if not os.path.exists(f) or os.path.isdir(f):
  74. continue
  75. if os.path.getmtime(f) != self.timestamps.get(f):
  76. print f + ' dirty'
  77. return True
  78. else:
  79. return False
  80. def make(self):
  81. """Build (stitch + compress) the file defined in build.json"""
  82. print "Building js and css files..."
  83. self.make_build_data()
  84. for builddict in self.bdata:
  85. outfile = builddict.keys()[0]
  86. infiles = self.get_infiles(builddict)
  87. self.concat(infiles, os.path.relpath(os.path.join(self.path, outfile), os.curdir))
  88. self.reset_app_html()
  89. def reset_app_html(self):
  90. import webnotes
  91. if os.path.exists("public/app.html"):
  92. os.remove("public/app.html")
  93. with open('lib/public/html/app.html', 'r') as app_html:
  94. data = app_html.read()
  95. data = data % {"_version_number": webnotes.generate_hash() }
  96. with open('public/app.html', 'w') as new_app_html:
  97. new_app_html.write(data)
  98. def get_infiles(self, builddict):
  99. """make list of files to merge"""
  100. outfile = builddict.keys()[0]
  101. infiles = builddict[outfile]
  102. # add app js and css to the list
  103. if outfile in self.appfiles:
  104. for f in self.appfiles[outfile]:
  105. if f not in infiles:
  106. infiles.append(f)
  107. fl = []
  108. for f in infiles:
  109. ## load files from directory
  110. if f.endswith('/'):
  111. # add init js first
  112. fl += [os.path.relpath(os.path.join(f, 'init.js'), os.curdir)]
  113. # files other than init.js and beginning with "_"
  114. fl += [os.path.relpath(os.path.join(f, tmp), os.curdir) \
  115. for tmp in os.listdir(f) if (tmp != 'init.js' and not tmp.startswith('_'))]
  116. else:
  117. fl.append(os.path.relpath(os.path.join(self.path, f), os.curdir))
  118. return fl
  119. def make_build_data(self):
  120. """merge build.json and lib/build.json"""
  121. # framework js and css files
  122. with open('lib/public/build.json', 'r') as bfile:
  123. bdata = eval(bfile.read())
  124. # app js and css files
  125. if os.path.exists('app/public/build.json'):
  126. with open('app/public/build.json', 'r') as bfile:
  127. appfiles = eval(bfile.read())
  128. else:
  129. appfiles = {}
  130. # add additional app files in bdata
  131. buildfile_list = [builddict.keys()[0] for builddict in bdata]
  132. for f in appfiles:
  133. if f not in buildfile_list:
  134. bdata.append({f: appfiles[f]})
  135. self.appfiles = appfiles
  136. self.bdata = bdata
  137. def check_public():
  138. from webnotes.install_lib.setup_public_folder import make
  139. make()
  140. def bundle(no_compress, cms_make=True):
  141. """concat / minify js files"""
  142. # build js files
  143. check_public()
  144. bundle = Bundle()
  145. bundle.no_compress = no_compress
  146. bundle.make()
  147. if cms_make:
  148. # build index.html and app.html
  149. from website.helpers.make_web_include_files import make
  150. make()
  151. def watch(no_compress):
  152. """watch and rebuild if necessary"""
  153. import time
  154. bundle = Bundle()
  155. bundle.no_compress = no_compress
  156. while True:
  157. if bundle.dirty():
  158. bundle.make()
  159. time.sleep(3)