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 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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