summaryrefslogtreecommitdiff
path: root/scripts/builder/frontendBuilder.py
Unidiff
Diffstat (limited to 'scripts/builder/frontendBuilder.py') (more/less context) (ignore whitespace changes)
-rw-r--r--scripts/builder/frontendBuilder.py141
1 files changed, 66 insertions, 75 deletions
diff --git a/scripts/builder/frontendBuilder.py b/scripts/builder/frontendBuilder.py
index 55054ee..dae837b 100644
--- a/scripts/builder/frontendBuilder.py
+++ b/scripts/builder/frontendBuilder.py
@@ -1,123 +1,90 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: UTF-8 -*- 2# -*- coding: UTF-8 -*-
3 3
4import sys, os, re 4import sys, os, re
5import cssmin 5import cssmin
6import jsmin 6import jsmin
7import codecs 7import codecs
8import shutil 8import shutil
9import StringIO 9import StringIO
10import urllib 10import urllib
11 11
12#from mercurial import ui, hg
13#from mercurial.node import hex
14from dulwich.repo import Repo
15
16import main 12import main
17 13
14class FrontendBuilder(object):
18 15
19 16 def __init__ (self, frontend, settings, repositoryVersion):
20class FrontendBuilder:
21
22 def __init__ (self, frontend, settings):
23 if '.' in frontend: 17 if '.' in frontend:
24 moduleComponents = frontend.split('.') 18 moduleComponents = frontend.split('.')
25 self.module = moduleComponents[0] 19 self.module = moduleComponents[0]
26 self.submodule = moduleComponents[1] 20 self.submodule = moduleComponents[1]
27 else: 21 else:
28 self.module = frontend 22 self.module = frontend
29 self.submodule = frontend 23 self.submodule = frontend
30 24
31 self.settings = settings 25 self.settings = settings
32 self.projectDir = main.projectBaseDir() 26 self.projectDir = main.projectBaseDir()
27 # self.repository = repository.repositoryWithPath(self.projectDir)
28 self.repositoryVersion = repositoryVersion
33 self.processedFiles = {} 29 self.processedFiles = {}
34 30
35 31
36 def mercurialRepositoryVersion (self):
37 repo = hg.repository(ui.ui(), self.projectDir)
38 context = repo['tip']
39 result = str(context)
40
41 return result
42
43
44 def gitRepositoryVersion (self):
45 repo = Repo(self.projectDir)
46 #if repo.is_dirty():
47 #print "WARNING: build run with dirty repository"
48 result = repo.refs['HEAD']
49
50 return result
51
52
53
54 def repositoryVersion (self):
55 cacheKey = 'repositoryVersion'
56 if not self.processedFiles.has_key(cacheKey):
57 #result = self.mercurialRepositoryVersion()
58 result = self.gitRepositoryVersion()
59 self.processedFiles[cacheKey] = result
60 else:
61 result = self.processedFiles[cacheKey]
62
63 return result
64
65
66 #def relativePath (self):
67 #return self.module
68 #
69
70 def log (self, message): 32 def log (self, message):
71 print "frontend [" + self.module + "]: " + message 33 print "frontend [" + self.module + "]: " + message
72 34
73 35
74 def absolutePathForSourceFile (self, folder, basePath, file): 36 def absolutePathForSources (self):
75 return folder + '/frontend/' + self.module + '/' + basePath + '/' + file 37 return os.path.join(self.projectDir, 'frontend', self.module)
38
39
40 def absolutePathForSourceFile (self, basePath, file):
41 return os.path.join(self.absolutePathForSources(), basePath, file)
76 42
77 43
78 def absolutePathForTargetFile (self, folder, basePath, file): 44 def absolutePathForTargetFile (self, folder, basePath, file):
79 return folder + '/' + self.module + '/' + basePath + '/' + file 45 return os.path.join(folder, self.module, basePath, file)
46
80 47
81 def filterFiles (self, files): 48 def filterFiles (self, files):
82 result = [] 49 result = []
83 50
84 for file in files: 51 for file in files:
85 if file.startswith('--'): 52 if file.startswith('--'):
86 pass 53 pass
87 else: 54 else:
88 result.append(file) 55 result.append(file)
89 56
90 return result 57 return result
91 58
92 59
93 def copyResources (self, sourceFolder, destinationFolder, fileType): 60 def copyResources (self, sourceFolder, destinationFolder, fileType):
94 for file in self.filterFiles(self.settings[fileType]): 61 for file in self.filterFiles(self.settings[fileType]):
95 src = self.absolutePathForSourceFile(sourceFolder, fileType, file) 62 src = self.absolutePathForSourceFile(fileType, file)
96 dst = self.absolutePathForTargetFile(destinationFolder, fileType, file) 63 dst = self.absolutePathForTargetFile(destinationFolder, fileType, file)
97 main.createFolder(os.path.dirname(dst)) 64 main.createFolder(os.path.dirname(dst))
98 shutil.copy2(src, dst) 65 shutil.copy2(src, dst)
99 66
100 67
101 def copyResourcesToTargetFolder (self, targetFolder): 68 def copyResourcesToFolder (self, targetFolder):
102 self.copyResources(self.projectDir, targetFolder, 'css') 69 self.copyResources(self.projectDir, targetFolder, 'css')
103 self.copyResources(self.projectDir, targetFolder, 'js') 70 self.copyResources(self.projectDir, targetFolder, 'js')
104 71
105 72
106 def loadFilesContent (self, basePath, files): 73 def loadFilesContent (self, basePath, files):
107 result = "" 74 result = ""
108 75
109 for file in self.filterFiles(files): 76 for file in self.filterFiles(files):
110 try: 77 try:
111 fileHandler = codecs.open(self.absolutePathForSourceFile(self.projectDir, basePath, file), 'r', 'utf-8') 78 fileHandler = codecs.open(self.absolutePathForSourceFile(basePath, file), 'r', 'utf-8')
112 except: 79 except:
113 print "FILE: " + file 80 print "FILE: " + file
114 81
115 result += fileHandler.read() + '\n' 82 result += fileHandler.read() + '\n'
116 fileHandler.close() 83 fileHandler.close()
117 84
118 return result 85 return result
119 86
120 87
121 def template (self): 88 def template (self):
122 processedFile = 'html_template' 89 processedFile = 'html_template'
123 if not self.processedFiles.has_key(processedFile): 90 if not self.processedFiles.has_key(processedFile):
@@ -172,71 +139,71 @@ class FrontendBuilder:
172 139
173 return css 140 return css
174 141
175 142
176 def compressCSS (self, css): 143 def compressCSS (self, css):
177 self.log("compressing CSS") 144 self.log("compressing CSS")
178 #return self.regexCssCompressor(css) 145 #return self.regexCssCompressor(css)
179 return self.cssminCompressor(css) 146 return self.cssminCompressor(css)
180 147
181 148
182 #========================================================================== 149 #==========================================================================
183 150
184 def compressJS_jsmin (self, js): 151 def compressJS_jsmin (self, js, description):
185 self.log("compressing JS code") 152 self.log("compressing " + description + " code")
186 original = StringIO.StringIO(js) 153 original = StringIO.StringIO(js)
187 output = StringIO.StringIO() 154 output = StringIO.StringIO()
188 155
189 jsMinifier = jsmin.JavascriptMinify() 156 jsMinifier = jsmin.JavascriptMinify()
190 jsMinifier.minify(original, output) 157 jsMinifier.minify(original, output)
191 158
192 result = output.getvalue() 159 result = output.getvalue()
193 160
194 original.close() 161 original.close()
195 output.close() 162 output.close()
196 163
197 return result 164 return result
198 165
199 def compressJS_closureCompiler (self, js): 166 def compressJS_closureCompiler (self, js, description):
200 #Googles Closure compiler 167 #Googles Closure compiler
201 #java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js 168 #java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js
202 169
203 result = js 170 result = js
204 171
205 return result 172 return result
206 173
207 174
208 def compressJS (self, js): 175 def compressJS (self, js, description):
209 return self.compressJS_jsmin(js) 176 return self.compressJS_jsmin(js, description)
210 #return self.compressJS_closureCompiler(js) 177 #return self.compressJS_closureCompiler(js, description)
211 178
212 179
213 #========================================================================== 180 #==========================================================================
214 181
215 def packBookmarklet (self, bookmakeletCode): 182 def packBookmarklet (self, bookmakeletCode, version):
216 replacers = [ 183 replacers = [
217 ('isLoginForm', 'ilf'), 184 ('isLoginForm', 'ilf'),
218 ('findLoginForm', 'flf'), 185 ('findLoginForm', 'flf'),
219 ('findLoginForm', 'flf'), 186 ('findLoginForm', 'flf'),
220 ('formParameters', 'fp' ), 187 ('formParameters', 'fp' ),
221 ('pageParameters', 'pp' ), 188 ('pageParameters', 'pp' ),
222 ('serializeJSON', 'sj' ), 189 ('serializeJSON', 'sj' ),
223 ('reprString', 'rs' ), 190 ('reprString', 'rs' ),
224 ('logFormParameters', 'lfp'), 191 ('logFormParameters', 'lfp'),
225 ('loadClipperzBookmarklet','lcb'), 192 ('loadClipperzBookmarklet','lcb'),
226 ('loginForm', 'lf' ), 193 ('loginForm', 'lf' ),
227 ('parameters', 'p' ), 194 ('parameters', 'p' ),
228 ('inputElementValues', 'iev'), 195 ('inputElementValues', 'iev'),
229 ] 196 ]
230 result = self.compressJS(bookmakeletCode) 197 result = self.compressJS(bookmakeletCode, version + " bookmarklet")
231 198
232 result = re.sub('\n', ' ', result) #Fit all in a single line 199 result = re.sub('\n', ' ', result) #Fit all in a single line
233 # result = re.sub('\s+', ' ', result) #Collapse "redundant" spaces. WARNING: this could have some evil side effects on constant strings used inside to code!! 200 # result = re.sub('\s+', ' ', result) #Collapse "redundant" spaces. WARNING: this could have some evil side effects on constant strings used inside to code!!
234 # result = re.sub('\s?([,\+=\(\)\{\};])\s?', '\\1', result) 201 # result = re.sub('\s?([,\+=\(\)\{\};])\s?', '\\1', result)
235 202
236 for replacer in replacers: 203 for replacer in replacers:
237 result = re.sub(replacer[0], replacer[1], result) 204 result = re.sub(replacer[0], replacer[1], result)
238 205
239 # <!-- escaping required to handle the bookmarklet code within the javascript code --> 206 # <!-- escaping required to handle the bookmarklet code within the javascript code -->
240 result = re.sub('\://', '%3a%2f%2f',result) 207 result = re.sub('\://', '%3a%2f%2f',result)
241 result = re.sub('/', '%2f', result) 208 result = re.sub('/', '%2f', result)
242 # result = re.sub('"', '%22', result) 209 # result = re.sub('"', '%22', result)
@@ -291,42 +258,42 @@ class FrontendBuilder:
291 # for replacer in replacers: 258 # for replacer in replacers:
292 # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result) 259 # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result)
293 260
294 # result = re.sub(';', ';\n', result) 261 # result = re.sub(';', ';\n', result)
295 262
296 return result 263 return result
297 264
298 265
299 266
300 def bookmarklet (self): 267 def bookmarklet (self):
301 cacheKey = 'bookmarklet' 268 cacheKey = 'bookmarklet'
302 if not self.processedFiles.has_key(cacheKey): 269 if not self.processedFiles.has_key(cacheKey):
303 result = 'bookmarklet="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet.js'])) + '";bookmarklet_ie="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet_IE.js'])) + '";' 270 result = 'bookmarklet="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet.js']), "regular") + '";bookmarklet_ie="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet_IE.js']), "IE") + '";'
304 self.processedFiles[cacheKey] = result 271 self.processedFiles[cacheKey] = result
305 else: 272 else:
306 result = self.processedFiles[cacheKey] 273 result = self.processedFiles[cacheKey]
307 274
308 return result 275 return result
309 276
310 277
311 def replaceTemplatePlaceholders (self, assemblyMode, pageTitle, copyright, css, code, version, versionType): 278 def replaceTemplatePlaceholders (self, pageTitle, copyright, css, code, jsLoadMode, version, versionType):
312 result = self.template() 279 result = self.template()
313 280
314 result = result.replace('@page.title@', pageTitle, 1) 281 result = result.replace('@page.title@', pageTitle, 1)
315 result = result.replace('@copyright@', copyright, 1) 282 result = result.replace('@copyright@', copyright, 1)
316 result = result.replace('@css@', css, 1) 283 result = result.replace('@css@', css, 1)
317 #result = result.replace('@bookmarklet@', bookmarklet,1) 284 #result = result.replace('@bookmarklet@', bookmarklet,1)
318 result = result.replace('@application.version@', version, 1) 285 result = result.replace('@application.version@', version, 1)
319 result = result.replace('@application.version.type@', versionType,1) 286 result = result.replace('@application.version.type@', versionType,1)
320 result = result.replace('@js_' + assemblyMode + '@', code, 1) 287 result = result.replace('@js_' + jsLoadMode + '@', code, 1)
321 288
322 result = re.sub('@js_[^@]+@', '', result) 289 result = re.sub('@js_[^@]+@', '', result)
323 290
324 return result 291 return result
325 292
326 293
327 def assembleCopyrightHeader (self): 294 def assembleCopyrightHeader (self):
328 processedFile = 'copyright' 295 processedFile = 'copyright'
329 if not self.processedFiles.has_key(processedFile): 296 if not self.processedFiles.has_key(processedFile):
330 #self.log("assembling copyright header") 297 #self.log("assembling copyright header")
331 copyrightValues = self.settings['copyright.values'] 298 copyrightValues = self.settings['copyright.values']
332 license = self.loadFilesContent('../../properties', ['license.txt']) 299 license = self.loadFilesContent('../../properties', ['license.txt'])
@@ -334,65 +301,89 @@ class FrontendBuilder:
334 301
335 result = re.sub('@clipperz.license@', license, result) 302 result = re.sub('@clipperz.license@', license, result)
336 for key in copyrightValues: 303 for key in copyrightValues:
337 result = re.sub('@'+key+'@', copyrightValues[key], result) 304 result = re.sub('@'+key+'@', copyrightValues[key], result)
338 305
339 self.processedFiles[processedFile] = result 306 self.processedFiles[processedFile] = result
340 307
341 return self.processedFiles[processedFile] 308 return self.processedFiles[processedFile]
342 309
343 310
344 def cssTagsForFiles (self, basePath, files): 311 def cssTagsForFiles (self, basePath, files):
345 #<link rel="stylesheet" type="text/css" href="./css/reset-min.css" /> 312 #<link rel="stylesheet" type="text/css" href="./css/reset-min.css" />
346 return '\n'.join(map(lambda file: '<link rel="stylesheet" type="text/css" href="./' + basePath + '/' + file + '" />', files)) 313 return '\n'.join(map(lambda file: '<link rel="stylesheet" type="text/css" href="' + basePath + '/' + file + '" />', files))
347 314
348 315
349 def cssTagForContent (self, content): 316 def cssTagForContent (self, content):
350 return '<style type="text/css">' + content + '</style>' 317 return '<style type="text/css">' + content + '</style>'
351 318
352 319
353 def scriptTagsForFiles (self, basePath, files): 320 def scriptTagsForFiles (self, basePath, files):
354 #<script type='text/javascript' src='./js/src/bookmarklet.js'></script> 321 #<script type='text/javascript' src='./js/src/bookmarklet.js'></script>
355 return '\n'.join(map(lambda file: '<script type="text/javascript" src="./' + basePath + '/' + file + '"></script>', files)) 322 return '\n'.join(map(lambda file: '<script type="text/javascript" src="' + basePath + '/' + file + '"></script>', files))
356 323
357 324
358 def scriptTagForContent (self, content): 325 def scriptTagForContent (self, content):
359 return '<script>' + content + '</script>' 326 return '<script>' + content + '</script>'
360 327
361 328
362 def assembleVersion (self, assemblyMode, pageTitle, copyright, css, js, version, versionType): 329 def assembleVersion (self, pageTitle, copyright, css, js, jsLoadMode, version, versionType):
363 cacheKey = version + "-" + versionType 330 cacheKey = version + "-" + versionType
364 if not self.processedFiles.has_key(cacheKey): 331 if not self.processedFiles.has_key(cacheKey):
365 result = self.replaceTemplatePlaceholders(assemblyMode, pageTitle, copyright, css, js, version, versionType) 332 result = self.replaceTemplatePlaceholders(pageTitle, copyright, css, js, jsLoadMode, version, versionType)
366 self.processedFiles[cacheKey] = result 333 self.processedFiles[cacheKey] = result
367 else: 334 else:
368 result = self.processedFiles[cacheKey] 335 result = self.processedFiles[cacheKey]
369 336
370 #self.log("# cacheKey:\n" + result) 337 #self.log("# cacheKey:\n" + result)
371 return result 338 return result
372 339
373 340
374 def assemble (self, assemblyMode='INSTALL', versionType='LIVE'): 341 def assemble (self, assemblyMode='INSTALL', versionType='LIVE'):
375 pageTitle = "Clipperz - " + self.module 342
376 if versionType != 'LIVE': 343 if versionType == 'LIVE':
377 pageTitle += " [" + versionType + " - " + assemblyMode +"]" 344 pageTitle = "Clipperz - " + self.module
378 345 else:
346 pageTitle = "Clipperz - " + self.module + " [" + versionType + " - " + assemblyMode +"]"
347
379 if assemblyMode == 'INSTALL': 348 if assemblyMode == 'INSTALL':
380 css= self.cssTagForContent(self.compressCSS(self.loadFilesContent('css', self.settings['css']))) 349 copyright = self.assembleCopyrightHeader()
381 js= self.scriptTagForContent(self.bookmarklet() + '\n' + self.compressJS(self.loadFilesContent('js', self.settings['js']))) 350 css =self.cssTagForContent(self.compressCSS(self.loadFilesContent('css', self.settings['css'])))
351 js =self.scriptTagForContent(
352 self.bookmarklet() +
353 '\n' +
354 self.compressJS(self.loadFilesContent('js', self.settings['js']), "application")
355 )
356 jsLoadMode = 'EMBEDDED'
357
358 elif assemblyMode == 'DEBUG':
359 copyright = self.assembleCopyrightHeader()
360 css =self.cssTagsForFiles('./css', self.filterFiles(self.settings['css']))
361 js =self.scriptTagForContent(self.bookmarklet()) + \
362 '\n' + \
363 self.scriptTagsForFiles('./js', self.filterFiles(self.settings['js']))
364 jsLoadMode = 'LINKED'
365
366 elif assemblyMode == 'DEVELOPMENT':
367 copyright = ""
368 css =self.cssTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'css')), self.filterFiles(self.settings['css']))
369 js =self.scriptTagForContent(self.bookmarklet()) + \
370 '\n' + \
371 self.scriptTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'js')), self.filterFiles(self.settings['js']))
372 jsLoadMode = 'LINKED'
373
382 else: 374 else:
383 css= self.cssTagsForFiles('css', self.filterFiles(self.settings['css'])) 375 raise NotImplementedError()
384 js= self.scriptTagForContent(self.bookmarklet()) + '\n' + self.scriptTagsForFiles('js', self.filterFiles(self.settings['js'])) 376
385
386 return self.assembleVersion( 377 return self.assembleVersion(
387 assemblyMode= assemblyMode,
388 pageTitle = pageTitle, 378 pageTitle = pageTitle,
389 copyright = self.assembleCopyrightHeader(), 379 copyright = copyright,
390 css = css, 380 css = css,
391 js = js, 381 js = js,
392 version = self.repositoryVersion(), 382 jsLoadMode = jsLoadMode,
383 version = self.repositoryVersion,
393 versionType = versionType 384 versionType = versionType
394 ) 385 )
395 386
396 387
397 388
398 389