Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

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