選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

227 行
5.5 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. from webnotes.utils.minify import JavascriptMinify
  5. """
  6. Build the `public` folders and setup languages
  7. """
  8. import os, sys, webnotes
  9. from cssmin import cssmin
  10. def bundle(no_compress, cms_make=True):
  11. """concat / minify js files"""
  12. # build js files
  13. webnotes.validate_versions()
  14. check_public()
  15. check_lang()
  16. bundle = Bundle()
  17. bundle.no_compress = no_compress
  18. bundle.make()
  19. if cms_make:
  20. try:
  21. from startup.event_handlers import on_build
  22. on_build()
  23. except ImportError, e:
  24. pass
  25. clear_pyc_files()
  26. def watch(no_compress):
  27. """watch and rebuild if necessary"""
  28. import time
  29. bundle = Bundle()
  30. bundle.no_compress = no_compress
  31. while True:
  32. if bundle.dirty():
  33. bundle.make()
  34. time.sleep(3)
  35. def check_public():
  36. from webnotes.install_lib.setup_public_folder import make
  37. make()
  38. def check_lang():
  39. from webnotes.translate import update_translations
  40. update_translations()
  41. def clear_pyc_files():
  42. from webnotes.utils import get_base_path
  43. for path, folders, files in os.walk(get_base_path()):
  44. if 'locale' in folders: folders.remove('locale')
  45. if 'files' in folders: folders.remove('files')
  46. if 'backups' in folders: folders.remove('backups')
  47. for f in files:
  48. if f.decode("utf-8").endswith(".pyc"):
  49. os.remove(os.path.join(path, f))
  50. class Bundle:
  51. """
  52. Concatenate, compress and mix (if required) js+css files from build.json
  53. """
  54. no_compress = False
  55. timestamps = {}
  56. path = '.'
  57. def concat(self, filelist, outfile=None):
  58. """
  59. Concat css and js files into a bundle
  60. """
  61. from cStringIO import StringIO
  62. out_type = outfile and outfile.split('.')[-1] or 'js'
  63. outtxt = ''
  64. for f in filelist:
  65. suffix = None
  66. if ':' in f:
  67. f, suffix = f.split(':')
  68. if not os.path.exists(f) or os.path.isdir(f):
  69. continue
  70. self.timestamps[f] = os.path.getmtime(f)
  71. # get datas
  72. try:
  73. with open(f, 'r') as infile:
  74. # get file type
  75. ftype = f.split('.')[-1]
  76. data = unicode(infile.read(), 'utf-8', errors='ignore')
  77. outtxt += ('\n/*\n *\t%s\n */' % f)
  78. # append
  79. if suffix=='concat' or out_type != 'js' or self.no_compress or ('.min.' in f):
  80. outtxt += '\n' + data + '\n'
  81. else:
  82. jsm = JavascriptMinify()
  83. tmpin = StringIO(data.encode('utf-8'))
  84. tmpout = StringIO()
  85. jsm.minify(tmpin, tmpout)
  86. tmpmin = unicode(tmpout.getvalue() or '', 'utf-8')
  87. tmpmin.strip('\n')
  88. outtxt += tmpmin
  89. except Exception, e:
  90. print "--Error in:" + f + "--"
  91. print webnotes.getTraceback()
  92. if not self.no_compress and out_type == 'css':
  93. outtxt = cssmin(outtxt)
  94. with open(outfile, 'w') as f:
  95. f.write(outtxt.encode("utf-8"))
  96. print "Wrote %s - %sk" % (outfile, str(int(os.path.getsize(outfile)/1024)))
  97. def dirty(self):
  98. """check if build files are dirty"""
  99. self.make_build_data()
  100. for builddict in self.bdata:
  101. for f in self.get_infiles(builddict):
  102. if ':' in f:
  103. f, suffix = f.split(':')
  104. if not os.path.exists(f) or os.path.isdir(f):
  105. continue
  106. if os.path.getmtime(f) != self.timestamps.get(f):
  107. print f + ' dirty'
  108. return True
  109. else:
  110. return False
  111. def make(self):
  112. """Build (stitch + compress) the file defined in build.json"""
  113. print "Building js and css files..."
  114. self.make_build_data()
  115. for builddict in self.bdata:
  116. outfile = builddict.keys()[0]
  117. infiles = self.get_infiles(builddict)
  118. self.concat(infiles, os.path.relpath(os.path.join(self.path, outfile), os.curdir))
  119. self.reset_app_html()
  120. def reset_app_html(self):
  121. import webnotes
  122. if os.path.exists("public/app.html"):
  123. os.remove("public/app.html")
  124. splash = ""
  125. if os.path.exists("public/app/images/splash.svg"):
  126. with open("public/app/images/splash.svg") as splash_file:
  127. splash = splash_file.read()
  128. with open('lib/public/html/app.html', 'r') as app_html:
  129. data = app_html.read()
  130. data = data % {
  131. "_version_number": webnotes.generate_hash(),
  132. "splash": splash
  133. }
  134. with open('public/app.html', 'w') as new_app_html:
  135. new_app_html.write(data)
  136. def get_infiles(self, builddict):
  137. """make list of files to merge"""
  138. outfile = builddict.keys()[0]
  139. infiles = builddict[outfile]
  140. # add app js and css to the list
  141. if outfile in self.appfiles:
  142. for f in self.appfiles[outfile]:
  143. if f not in infiles:
  144. infiles.append(f)
  145. fl = []
  146. for f in infiles:
  147. ## load files from directory
  148. if f.endswith('/'):
  149. # add init js first
  150. fl += [os.path.relpath(os.path.join(f, 'init.js'), os.curdir)]
  151. # files other than init.js and beginning with "_"
  152. fl += [os.path.relpath(os.path.join(f, tmp), os.curdir) \
  153. for tmp in os.listdir(f) if (tmp != 'init.js' and not tmp.startswith('_'))]
  154. else:
  155. fl.append(os.path.relpath(os.path.join(self.path, f), os.curdir))
  156. return fl
  157. def make_build_data(self):
  158. """merge build.json and lib/build.json"""
  159. # framework js and css files
  160. with open('lib/public/build.json', 'r') as bfile:
  161. bdata = eval(bfile.read())
  162. # app js and css files
  163. if os.path.exists('app/public/build.json'):
  164. with open('app/public/build.json', 'r') as bfile:
  165. appfiles = eval(bfile.read())
  166. else:
  167. appfiles = {}
  168. # add additional app files in bdata
  169. buildfile_list = [builddict.keys()[0] for builddict in bdata]
  170. for f in appfiles:
  171. if f not in buildfile_list:
  172. bdata.append({f: appfiles[f]})
  173. self.appfiles = appfiles
  174. self.bdata = bdata