Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

224 linhas
5.4 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. for f in files:
  46. if f.decode("utf-8").endswith(".pyc"):
  47. os.remove(os.path.join(path, f))
  48. class Bundle:
  49. """
  50. Concatenate, compress and mix (if required) js+css files from build.json
  51. """
  52. no_compress = False
  53. timestamps = {}
  54. path = '.'
  55. def concat(self, filelist, outfile=None):
  56. """
  57. Concat css and js files into a bundle
  58. """
  59. from cStringIO import StringIO
  60. out_type = outfile and outfile.split('.')[-1] or 'js'
  61. outtxt = ''
  62. for f in filelist:
  63. suffix = None
  64. if ':' in f:
  65. f, suffix = f.split(':')
  66. if not os.path.exists(f) or os.path.isdir(f):
  67. continue
  68. self.timestamps[f] = os.path.getmtime(f)
  69. # get datas
  70. try:
  71. with open(f, 'r') as infile:
  72. # get file type
  73. ftype = f.split('.')[-1]
  74. data = unicode(infile.read(), 'utf-8', errors='ignore')
  75. outtxt += ('\n/*\n *\t%s\n */' % f)
  76. # append
  77. if suffix=='concat' or out_type != 'js' or self.no_compress or ('.min.' in f):
  78. outtxt += '\n' + data + '\n'
  79. else:
  80. jsm = JavascriptMinify()
  81. tmpin = StringIO(data.encode('utf-8'))
  82. tmpout = StringIO()
  83. jsm.minify(tmpin, tmpout)
  84. tmpmin = unicode(tmpout.getvalue() or '', 'utf-8')
  85. tmpmin.strip('\n')
  86. outtxt += tmpmin
  87. except Exception, e:
  88. print "--Error in:" + f + "--"
  89. print webnotes.getTraceback()
  90. if not self.no_compress and out_type == 'css':
  91. outtxt = cssmin(outtxt)
  92. with open(outfile, 'w') as f:
  93. f.write(outtxt.encode("utf-8"))
  94. print "Wrote %s - %sk" % (outfile, str(int(os.path.getsize(outfile)/1024)))
  95. def dirty(self):
  96. """check if build files are dirty"""
  97. self.make_build_data()
  98. for builddict in self.bdata:
  99. for f in self.get_infiles(builddict):
  100. if ':' in f:
  101. f, suffix = f.split(':')
  102. if not os.path.exists(f) or os.path.isdir(f):
  103. continue
  104. if os.path.getmtime(f) != self.timestamps.get(f):
  105. print f + ' dirty'
  106. return True
  107. else:
  108. return False
  109. def make(self):
  110. """Build (stitch + compress) the file defined in build.json"""
  111. print "Building js and css files..."
  112. self.make_build_data()
  113. for builddict in self.bdata:
  114. outfile = builddict.keys()[0]
  115. infiles = self.get_infiles(builddict)
  116. self.concat(infiles, os.path.relpath(os.path.join(self.path, outfile), os.curdir))
  117. self.reset_app_html()
  118. def reset_app_html(self):
  119. import webnotes
  120. if os.path.exists("public/app.html"):
  121. os.remove("public/app.html")
  122. splash = ""
  123. if os.path.exists("public/app/images/splash.svg"):
  124. with open("public/app/images/splash.svg") as splash_file:
  125. splash = splash_file.read()
  126. with open('lib/public/html/app.html', 'r') as app_html:
  127. data = app_html.read()
  128. data = data % {
  129. "_version_number": webnotes.generate_hash(),
  130. "splash": splash
  131. }
  132. with open('public/app.html', 'w') as new_app_html:
  133. new_app_html.write(data)
  134. def get_infiles(self, builddict):
  135. """make list of files to merge"""
  136. outfile = builddict.keys()[0]
  137. infiles = builddict[outfile]
  138. # add app js and css to the list
  139. if outfile in self.appfiles:
  140. for f in self.appfiles[outfile]:
  141. if f not in infiles:
  142. infiles.append(f)
  143. fl = []
  144. for f in infiles:
  145. ## load files from directory
  146. if f.endswith('/'):
  147. # add init js first
  148. fl += [os.path.relpath(os.path.join(f, 'init.js'), os.curdir)]
  149. # files other than init.js and beginning with "_"
  150. fl += [os.path.relpath(os.path.join(f, tmp), os.curdir) \
  151. for tmp in os.listdir(f) if (tmp != 'init.js' and not tmp.startswith('_'))]
  152. else:
  153. fl.append(os.path.relpath(os.path.join(self.path, f), os.curdir))
  154. return fl
  155. def make_build_data(self):
  156. """merge build.json and lib/build.json"""
  157. # framework js and css files
  158. with open('lib/public/build.json', 'r') as bfile:
  159. bdata = eval(bfile.read())
  160. # app js and css files
  161. if os.path.exists('app/public/build.json'):
  162. with open('app/public/build.json', 'r') as bfile:
  163. appfiles = eval(bfile.read())
  164. else:
  165. appfiles = {}
  166. # add additional app files in bdata
  167. buildfile_list = [builddict.keys()[0] for builddict in bdata]
  168. for f in appfiles:
  169. if f not in buildfile_list:
  170. bdata.append({f: appfiles[f]})
  171. self.appfiles = appfiles
  172. self.bdata = bdata