Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

194 rindas
5.2 KiB

  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 = infile.read()
  51. if os.path.basename(f)=='core.js':
  52. import webnotes
  53. data = data % {"_version_number": webnotes.generate_hash() }
  54. outtxt += ('\n/*\n *\t%s\n */' % f)
  55. # append
  56. if suffix=='concat' or out_type != 'js' or self.no_compress or ('.min.' in f):
  57. outtxt += '\n' + data + '\n'
  58. else:
  59. jsm = JavascriptMinify()
  60. tmpin = StringIO(data)
  61. tmpout = StringIO()
  62. jsm.minify(tmpin, tmpout)
  63. tmpmin = tmpout.getvalue() or ''
  64. tmpmin.strip('\n')
  65. outtxt += tmpmin
  66. with open(outfile, 'w') as f:
  67. f.write(outtxt)
  68. print "Wrote %s - %sk" % (outfile, str(int(os.path.getsize(outfile)/1024)))
  69. def dirty(self):
  70. """check if build files are dirty"""
  71. self.make_build_data()
  72. for builddict in self.bdata:
  73. for f in self.get_infiles(builddict):
  74. if ':' in f:
  75. f, suffix = f.split(':')
  76. if not os.path.exists(f) or os.path.isdir(f):
  77. continue
  78. if os.path.getmtime(f) != self.timestamps.get(f):
  79. print f + ' dirty'
  80. return True
  81. else:
  82. return False
  83. def make(self):
  84. """Build (stitch + compress) the file defined in build.json"""
  85. print "Building js and css files..."
  86. self.make_build_data()
  87. for builddict in self.bdata:
  88. outfile = builddict.keys()[0]
  89. infiles = self.get_infiles(builddict)
  90. self.concat(infiles, os.path.relpath(os.path.join(self.path, outfile), os.curdir))
  91. def get_infiles(self, builddict):
  92. """make list of files to merge"""
  93. outfile = builddict.keys()[0]
  94. infiles = builddict[outfile]
  95. # add app js and css to the list
  96. if outfile in self.appfiles:
  97. for f in self.appfiles[outfile]:
  98. if f not in infiles:
  99. infiles.append(f)
  100. fl = []
  101. for f in infiles:
  102. ## load files from directory
  103. if f.endswith('/'):
  104. # add init js first
  105. fl += [os.path.relpath(os.path.join(f, 'init.js'), os.curdir)]
  106. # files other than init.js and beginning with "_"
  107. fl += [os.path.relpath(os.path.join(f, tmp), os.curdir) \
  108. for tmp in os.listdir(f) if (tmp != 'init.js' and not tmp.startswith('_'))]
  109. else:
  110. fl.append(os.path.relpath(os.path.join(self.path, f), os.curdir))
  111. return fl
  112. def make_build_data(self):
  113. """merge build.json and lib/build.json"""
  114. # framework js and css files
  115. with open('lib/public/build.json', 'r') as bfile:
  116. bdata = eval(bfile.read())
  117. # app js and css files
  118. if os.path.exists('app/public/build.json'):
  119. with open('app/public/build.json', 'r') as bfile:
  120. appfiles = eval(bfile.read())
  121. else:
  122. appfiles = {}
  123. # add additional app files in bdata
  124. buildfile_list = [builddict.keys()[0] for builddict in bdata]
  125. for f in appfiles:
  126. if f not in buildfile_list:
  127. bdata.append({f: appfiles[f]})
  128. self.appfiles = appfiles
  129. self.bdata = bdata
  130. def check_public():
  131. from webnotes.install_lib.setup_public_folder import make
  132. make()
  133. def bundle(no_compress, cms_make=True):
  134. """concat / minify js files"""
  135. # build js files
  136. check_public()
  137. bundle = Bundle()
  138. bundle.no_compress = no_compress
  139. bundle.make()
  140. if cms_make:
  141. # build index.html and app.html
  142. import webnotes.cms.make
  143. webnotes.cms.make.make()
  144. def watch(no_compress):
  145. """watch and rebuild if necessary"""
  146. import time
  147. bundle = Bundle()
  148. bundle.no_compress = no_compress
  149. while True:
  150. if bundle.dirty():
  151. bundle.make()
  152. time.sleep(3)