You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
13 年之前
12 年之前
14 年之前
12 年之前
14 年之前
13 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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