No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

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