Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

213 строки
5.0 KiB

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