author | Josh <jokajak@gmail.com> | 2012-03-17 19:29:33 (UTC) |
---|---|---|
committer | Josh <jokajak@gmail.com> | 2012-03-17 19:29:33 (UTC) |
commit | 0e396afdc4aa9ec8734ba48f90e9fefbad3b2b33 (patch) (unidiff) | |
tree | 2ace8ec32d24c1d34b4578fe9297c4e4b4b97720 /scripts | |
parent | ff33328861685c1a2d5f9b729a2b3595509c38ee (diff) | |
parent | 6f7ead0446aae6dd9f40b183e402b059a33d0517 (diff) | |
download | clipperz-0e396afdc4aa9ec8734ba48f90e9fefbad3b2b33.zip clipperz-0e396afdc4aa9ec8734ba48f90e9fefbad3b2b33.tar.gz clipperz-0e396afdc4aa9ec8734ba48f90e9fefbad3b2b33.tar.bz2 |
Merge remote-tracking branch 'upstream/master'
-rw-r--r-- | scripts/builder/backendBuilder.py | 21 | ||||
-rw-r--r-- | scripts/builder/frontendBuilder.py | 5 | ||||
-rw-r--r-- | scripts/builder/repository.py | 18 |
3 files changed, 31 insertions, 13 deletions
diff --git a/scripts/builder/backendBuilder.py b/scripts/builder/backendBuilder.py index 3e61955..5b91678 100644 --- a/scripts/builder/backendBuilder.py +++ b/scripts/builder/backendBuilder.py | |||
@@ -1,118 +1,131 @@ | |||
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | # -*- coding: UTF-8 -*- | 2 | # -*- coding: UTF-8 -*- |
3 | 3 | ||
4 | import sys, os, json | 4 | import sys, os, json |
5 | import shutil | 5 | import shutil |
6 | import hashlib | 6 | import hashlib |
7 | 7 | ||
8 | import main | 8 | import main |
9 | 9 | ||
10 | #=================================================================== | 10 | #=================================================================== |
11 | 11 | ||
12 | 12 | ||
13 | class BackendBuilder(object): | 13 | class BackendBuilder(object): |
14 | 14 | ||
15 | def __init__ (self, projectTargetDir, frontends, versions, settings): | 15 | def __init__ (self, projectTargetDir, frontends, versions, settings): |
16 | self.projectTargetDir = projectTargetDir | 16 | self.projectTargetDir = projectTargetDir |
17 | self.frontends = frontends | 17 | self.frontends = frontends |
18 | self.versions = versions | 18 | self.versions = versions |
19 | self.settings = settings | 19 | self.settings = settings |
20 | 20 | ||
21 | # -------------------------------------------------------------------------- | 21 | # -------------------------------------------------------------------------- |
22 | 22 | ||
23 | def name (self): | 23 | def name (self): |
24 | raise NotImplementedError() | 24 | raise NotImplementedError() |
25 | 25 | ||
26 | 26 | ||
27 | def relativePath (self): | 27 | def relativePath (self): |
28 | raise NotImplementedError() | 28 | raise NotImplementedError() |
29 | 29 | ||
30 | 30 | ||
31 | def compileCode (self): | 31 | def compileCode (self): |
32 | raise NotImplementedError() | 32 | raise NotImplementedError() |
33 | 33 | ||
34 | 34 | ||
35 | def createPackage (self): | 35 | def createPackage (self): |
36 | raise NotImplementedError() | 36 | raise NotImplementedError() |
37 | 37 | ||
38 | # -------------------------------------------------------------------------- | 38 | # -------------------------------------------------------------------------- |
39 | 39 | ||
40 | def sourceFolder (self): | 40 | def sourceFolder (self): |
41 | return os.path.join(main.projectBaseDir() , 'backend', self.relativePath(), 'src') | 41 | return os.path.join(main.projectBaseDir() , 'backend', self.relativePath(), 'src') |
42 | 42 | ||
43 | 43 | ||
44 | def tempFolder (self): | 44 | def tempFolder (self): |
45 | return os.path.join(self.projectTargetDir, '.tmp', self.relativePath()) | 45 | return os.path.join(self.projectTargetDir, '.tmp', self.relativePath()) |
46 | 46 | ||
47 | 47 | ||
48 | def frontEndTempFolder (self): | 48 | def frontEndTempFolder (self): |
49 | return self.tempFolder() | 49 | return self.tempFolder() |
50 | 50 | ||
51 | 51 | ||
52 | def developmentTargetFolder (self): | 52 | def developmentTargetFolder (self): |
53 | return os.path.join(self.projectTargetDir, 'development', self.relativePath()) | 53 | return os.path.join(self.projectTargetDir, 'development', self.relativePath()) |
54 | 54 | ||
55 | def targetFolder (self): | 55 | def targetFolder (self): |
56 | return os.path.join(self.projectTargetDir, self.relativePath()) | 56 | return os.path.join(self.projectTargetDir, self.relativePath()) |
57 | 57 | ||
58 | # -------------------------------------------------------------------------- | 58 | # -------------------------------------------------------------------------- |
59 | 59 | ||
60 | def writeToFolder (self, folder, filename, content): | 60 | def writeToFolder (self, folder, filename, content): |
61 | file = open(os.path.join(folder, filename), 'w') | 61 | file = open(os.path.join(folder, filename), 'w') |
62 | file.write(content.encode('utf-8')) | 62 | file.write(content.encode('utf-8')) |
63 | file.close() | 63 | file.close() |
64 | 64 | ||
65 | 65 | ||
66 | def configureIndexContent (self, indexContent, requestPathPrefix = ".."): | 66 | def configureIndexContent (self, indexContent, requestPathPrefix = ".."): |
67 | result = indexContent | 67 | result = indexContent |
68 | result = result.replace( '@request.path@', requestPathPrefix + '/' + self.settings['request.path'] ) | 68 | result = result.replace( '@request.path@', requestPathPrefix + '/' + self.settings['request.path'] ) |
69 | result = result.replace( '@should.pay.toll@', self.settings['should.pay.toll'] ) | 69 | result = result.replace( '@should.pay.toll@', self.settings['should.pay.toll'] ) |
70 | 70 | ||
71 | return result | 71 | return result |
72 | 72 | ||
73 | 73 | ||
74 | def logChecksums (self, content, message): | 74 | def logChecksums (self, content, message): |
75 | md5Digest = hashlib.md5(content.encode('utf-8')).hexdigest() | 75 | md5Digest = hashlib.md5(content.encode('utf-8')).hexdigest() |
76 | shaDigest = hashlib.sha1(content.encode('utf-8')).hexdigest() | 76 | shaDigest = hashlib.sha1(content.encode('utf-8')).hexdigest() |
77 | sha256Digest= hashlib.sha256(content.encode('utf-8')).hexdigest() | 77 | sha256Digest= hashlib.sha256(content.encode('utf-8')).hexdigest() |
78 | print message + ": " + md5Digest + " (md5)" | 78 | print message + ": " + md5Digest + " (md5)" |
79 | print message + ": " + shaDigest + " (sha1)" | 79 | print message + ": " + shaDigest + " (sha1)" |
80 | print message + ": " + sha256Digest + " (sha256)" | 80 | print message + ": " + sha256Digest + " (sha256)" |
81 | 81 | ||
82 | 82 | ||
83 | def shouldCompileCode (self): | 83 | def shouldCompileCode (self): |
84 | return ('debug' in self.versions) or ('install' in self.versions) | 84 | return ('debug' in self.versions) or ('install' in self.versions) |
85 | 85 | ||
86 | 86 | ||
87 | def run (self): | 87 | def run (self): |
88 | print self.name() + " - RUN" | 88 | print self.name() + " - RUN" |
89 | 89 | ||
90 | if self.shouldCompileCode(): | 90 | if self.shouldCompileCode(): |
91 | self.compileCode() | 91 | self.compileCode() |
92 | 92 | ||
93 | for frontend in self.frontends: | 93 | for frontend in self.frontends: |
94 | if (frontend.module == frontend.submodule): | ||
95 | submoduleExtension = '' | ||
96 | else: | ||
97 | submoduleExtension = '.' + frontend.submodule | ||
98 | |||
94 | main.createFolder(os.path.join(self.frontEndTempFolder(), frontend.module)) | 99 | main.createFolder(os.path.join(self.frontEndTempFolder(), frontend.module)) |
95 | 100 | ||
96 | if 'debug' in self.versions: | 101 | if 'debug' in self.versions: |
97 | frontend.copyResourcesToFolder(self.frontEndTempFolder()) | 102 | frontend.copyResourcesToFolder(self.frontEndTempFolder()) |
98 | 103 | ||
99 | index = self.configureIndexContent(frontend.assemble(assemblyMode='DEBUG', versionType='DEBUG')) | 104 | index = self.configureIndexContent(frontend.assemble(assemblyMode='DEBUG', versionType='DEBUG')) |
100 | self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index_debug.html'), index) | 105 | self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index_debug' + submoduleExtension + '.html'), index) |
101 | 106 | ||
102 | if 'install' in self.versions: | 107 | if 'install' in self.versions: |
103 | index = self.configureIndexContent(frontend.assemble()) | 108 | index = self.configureIndexContent(frontend.assemble()) |
104 | self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index.html'), index) | 109 | self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index' + submoduleExtension + '.html'), index) |
105 | 110 | ||
106 | self.logChecksums(index, "[" + self.name() + " - " + frontend.module + "] index.html checksum") | 111 | self.logChecksums(index, "[" + self.name() + " - " + frontend.module + "] index" + submoduleExtension + ".html checksum") |
107 | 112 | ||
108 | self.createPackage() | 113 | self.createPackage() |
109 | 114 | ||
110 | if 'development' in self.versions: | 115 | if 'development' in self.versions: |
111 | for frontend in self.frontends: | 116 | for frontend in self.frontends: |
117 | if (frontend.module == frontend.submodule): | ||
118 | submoduleExtension = '' | ||
119 | else: | ||
120 | submoduleExtension = '.' + frontend.submodule | ||
121 | |||
122 | print "FRONTEND module: " + frontend.module | ||
123 | print "FRONTEND submodule: " + frontend.submodule | ||
124 | |||
112 | main.createFolder(os.path.join(self.developmentTargetFolder(), frontend.module)) | 125 | main.createFolder(os.path.join(self.developmentTargetFolder(), frontend.module)) |
113 | 126 | ||
114 | index = self.configureIndexContent(frontend.assemble(assemblyMode='DEVELOPMENT', versionType='DEBUG'), self.settings['development.settings']['url']) | 127 | index = self.configureIndexContent(frontend.assemble(assemblyMode='DEVELOPMENT', versionType='DEBUG'), self.settings['development.settings']['url']) |
115 | self.writeToFolder(self.developmentTargetFolder(), os.path.join(frontend.module, 'index.html'), index) | 128 | self.writeToFolder(self.developmentTargetFolder(), os.path.join(frontend.module, 'index' + submoduleExtension + '.html'), index) |
116 | 129 | ||
117 | 130 | ||
118 | #=================================================================== | 131 | #=================================================================== |
diff --git a/scripts/builder/frontendBuilder.py b/scripts/builder/frontendBuilder.py index dae837b..1f0f92f 100644 --- a/scripts/builder/frontendBuilder.py +++ b/scripts/builder/frontendBuilder.py | |||
@@ -1,389 +1,390 @@ | |||
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | # -*- coding: UTF-8 -*- | 2 | # -*- coding: UTF-8 -*- |
3 | 3 | ||
4 | import sys, os, re | 4 | import sys, os, re |
5 | import cssmin | 5 | import cssmin |
6 | import jsmin | 6 | import jsmin |
7 | import codecs | 7 | import codecs |
8 | import shutil | 8 | import shutil |
9 | import StringIO | 9 | import StringIO |
10 | import urllib | 10 | import urllib |
11 | 11 | ||
12 | import main | 12 | import main |
13 | 13 | ||
14 | class FrontendBuilder(object): | 14 | class FrontendBuilder(object): |
15 | 15 | ||
16 | def __init__ (self, frontend, settings, repositoryVersion): | 16 | def __init__ (self, frontend, settings, repositoryVersion): |
17 | if '.' in frontend: | 17 | if '.' in frontend: |
18 | moduleComponents = frontend.split('.') | 18 | moduleComponents = frontend.split('.') |
19 | self.module = moduleComponents[0] | 19 | self.module = moduleComponents[0] |
20 | self.submodule = moduleComponents[1] | 20 | self.submodule = moduleComponents[1] |
21 | else: | 21 | else: |
22 | self.module = frontend | 22 | self.module = frontend |
23 | self.submodule = frontend | 23 | self.submodule = frontend |
24 | 24 | ||
25 | self.settings = settings | 25 | self.settings = settings |
26 | self.projectDir = main.projectBaseDir() | 26 | self.projectDir = main.projectBaseDir() |
27 | # self.repository = repository.repositoryWithPath(self.projectDir) | 27 | # self.repository = repository.repositoryWithPath(self.projectDir) |
28 | self.repositoryVersion = repositoryVersion | 28 | self.repositoryVersion = repositoryVersion |
29 | self.processedFiles = {} | 29 | self.processedFiles = {} |
30 | 30 | ||
31 | 31 | ||
32 | def log (self, message): | 32 | def log (self, message): |
33 | print "frontend [" + self.module + "]: " + message | 33 | print "frontend [" + self.module + "]: " + message |
34 | 34 | ||
35 | 35 | ||
36 | def absolutePathForSources (self): | 36 | def absolutePathForSources (self): |
37 | return os.path.join(self.projectDir, 'frontend', self.module) | 37 | return os.path.join(self.projectDir, 'frontend', self.module) |
38 | 38 | ||
39 | 39 | ||
40 | def absolutePathForSourceFile (self, basePath, file): | 40 | def absolutePathForSourceFile (self, basePath, file): |
41 | return os.path.join(self.absolutePathForSources(), basePath, file) | 41 | return os.path.join(self.absolutePathForSources(), basePath, file) |
42 | 42 | ||
43 | 43 | ||
44 | def absolutePathForTargetFile (self, folder, basePath, file): | 44 | def absolutePathForTargetFile (self, folder, basePath, file): |
45 | return os.path.join(folder, self.module, basePath, file) | 45 | return os.path.join(folder, self.module, basePath, file) |
46 | 46 | ||
47 | 47 | ||
48 | def filterFiles (self, files): | 48 | def filterFiles (self, files): |
49 | result = [] | 49 | result = [] |
50 | 50 | ||
51 | for file in files: | 51 | for file in files: |
52 | if file.startswith('--'): | 52 | if file.startswith('--'): |
53 | pass | 53 | pass |
54 | else: | 54 | else: |
55 | result.append(file) | 55 | result.append(file) |
56 | 56 | ||
57 | return result | 57 | return result |
58 | 58 | ||
59 | 59 | ||
60 | def copyResources (self, sourceFolder, destinationFolder, fileType): | 60 | def copyResources (self, sourceFolder, destinationFolder, fileType): |
61 | for file in self.filterFiles(self.settings[fileType]): | 61 | for file in self.filterFiles(self.settings[fileType]): |
62 | src = self.absolutePathForSourceFile(fileType, file) | 62 | src = self.absolutePathForSourceFile(fileType, file) |
63 | dst = self.absolutePathForTargetFile(destinationFolder, fileType, file) | 63 | dst = self.absolutePathForTargetFile(destinationFolder, fileType, file) |
64 | main.createFolder(os.path.dirname(dst)) | 64 | main.createFolder(os.path.dirname(dst)) |
65 | shutil.copy2(src, dst) | 65 | shutil.copy2(src, dst) |
66 | 66 | ||
67 | 67 | ||
68 | def copyResourcesToFolder (self, targetFolder): | 68 | def copyResourcesToFolder (self, targetFolder): |
69 | self.copyResources(self.projectDir, targetFolder, 'css') | 69 | self.copyResources(self.projectDir, targetFolder, 'css') |
70 | self.copyResources(self.projectDir, targetFolder, 'js') | 70 | self.copyResources(self.projectDir, targetFolder, 'js') |
71 | 71 | ||
72 | 72 | ||
73 | def loadFilesContent (self, basePath, files): | 73 | def loadFilesContent (self, basePath, files): |
74 | result = "" | 74 | result = "" |
75 | 75 | ||
76 | for file in self.filterFiles(files): | 76 | for file in self.filterFiles(files): |
77 | try: | 77 | try: |
78 | fileHandler = codecs.open(self.absolutePathForSourceFile(basePath, file), 'r', 'utf-8') | 78 | fileHandler = codecs.open(self.absolutePathForSourceFile(basePath, file), 'r', 'utf-8') |
79 | except: | 79 | except: |
80 | print "FILE: " + file | 80 | print "FILE: " + file |
81 | 81 | ||
82 | result += fileHandler.read() + '\n' | 82 | result += fileHandler.read() + '\n' |
83 | fileHandler.close() | 83 | fileHandler.close() |
84 | 84 | ||
85 | return result | 85 | return result |
86 | 86 | ||
87 | 87 | ||
88 | def template (self): | 88 | def template (self): |
89 | processedFile = 'html_template' | 89 | processedFile = 'html_template' |
90 | if not self.processedFiles.has_key(processedFile): | 90 | if not self.processedFiles.has_key(processedFile): |
91 | self.processedFiles[processedFile] = self.loadFilesContent('html', ['index_template.html']) | 91 | #self.processedFiles[processedFile] = self.loadFilesContent('html', ['index_template.html']) |
92 | self.processedFiles[processedFile] = self.loadFilesContent('html', [self.settings['html.template']]) | ||
92 | 93 | ||
93 | return self.processedFiles[processedFile] | 94 | return self.processedFiles[processedFile] |
94 | 95 | ||
95 | 96 | ||
96 | def cssminCompressor (self, css): | 97 | def cssminCompressor (self, css): |
97 | # package found here: | 98 | # package found here: |
98 | # - http://stackoverflow.com/questions/222581/python-script-for-minifying-css/2396777#2396777 | 99 | # - http://stackoverflow.com/questions/222581/python-script-for-minifying-css/2396777#2396777 |
99 | # actual downloaded version: http://pypi.python.org/pypi/cssmin/0.1.4 | 100 | # actual downloaded version: http://pypi.python.org/pypi/cssmin/0.1.4 |
100 | return cssmin.cssmin(css) | 101 | return cssmin.cssmin(css) |
101 | 102 | ||
102 | 103 | ||
103 | def regexCssCompressor (self, css): | 104 | def regexCssCompressor (self, css): |
104 | # http://stackoverflow.com/questions/222581/python-script-for-minifying-css/223689#223689 | 105 | # http://stackoverflow.com/questions/222581/python-script-for-minifying-css/223689#223689 |
105 | 106 | ||
106 | # remove comments - this will break a lot of hacks :-P | 107 | # remove comments - this will break a lot of hacks :-P |
107 | css = re.sub( r'\s*/\*\s*\*/', "$$HACK1$$", css ) # preserve IE<6 comment hack | 108 | css = re.sub( r'\s*/\*\s*\*/', "$$HACK1$$", css ) # preserve IE<6 comment hack |
108 | css = re.sub( r'/\*[\s\S]*?\*/', "", css ) | 109 | css = re.sub( r'/\*[\s\S]*?\*/', "", css ) |
109 | css = css.replace( "$$HACK1$$", '/**/' ) # preserve IE<6 comment hack | 110 | css = css.replace( "$$HACK1$$", '/**/' ) # preserve IE<6 comment hack |
110 | 111 | ||
111 | # url() doesn't need quotes | 112 | # url() doesn't need quotes |
112 | css = re.sub( r'url\((["\'])([^)]*)\1\)', r'url(\2)', css ) | 113 | css = re.sub( r'url\((["\'])([^)]*)\1\)', r'url(\2)', css ) |
113 | 114 | ||
114 | # spaces may be safely collapsed as generated content will collapse them anyway | 115 | # spaces may be safely collapsed as generated content will collapse them anyway |
115 | css = re.sub( r'\s+', ' ', css ) | 116 | css = re.sub( r'\s+', ' ', css ) |
116 | 117 | ||
117 | # shorten collapsable colors: #aabbcc to #abc | 118 | # shorten collapsable colors: #aabbcc to #abc |
118 | css = re.sub( r'#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)', r'#\1\2\3\4', css ) | 119 | css = re.sub( r'#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)', r'#\1\2\3\4', css ) |
119 | 120 | ||
120 | # fragment values can loose zeros | 121 | # fragment values can loose zeros |
121 | css = re.sub( r':\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;', r':\1;', css ) | 122 | css = re.sub( r':\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;', r':\1;', css ) |
122 | 123 | ||
123 | for rule in re.findall( r'([^{]+){([^}]*)}', css ): | 124 | for rule in re.findall( r'([^{]+){([^}]*)}', css ): |
124 | 125 | ||
125 | # we don't need spaces around operators | 126 | # we don't need spaces around operators |
126 | selectors = [re.sub( r'(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])', r'', selector.strip() ) for selector in rule[0].split( ',' )] | 127 | selectors = [re.sub( r'(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])', r'', selector.strip() ) for selector in rule[0].split( ',' )] |
127 | 128 | ||
128 | # order is important, but we still want to discard repetitions | 129 | # order is important, but we still want to discard repetitions |
129 | properties = {} | 130 | properties = {} |
130 | porder = [] | 131 | porder = [] |
131 | for prop in re.findall( '(.*?):(.*?)(;|$)', rule[1] ): | 132 | for prop in re.findall( '(.*?):(.*?)(;|$)', rule[1] ): |
132 | key = prop[0].strip().lower() | 133 | key = prop[0].strip().lower() |
133 | if key not in porder: porder.append( key ) | 134 | if key not in porder: porder.append( key ) |
134 | properties[ key ] = prop[1].strip() | 135 | properties[ key ] = prop[1].strip() |
135 | 136 | ||
136 | # output rule if it contains any declarations | 137 | # output rule if it contains any declarations |
137 | if properties: | 138 | if properties: |
138 | print "%s{%s}" % ( ','.join( selectors ), ''.join(['%s:%s;' % (key, properties[key]) for key in porder])[:-1] ) | 139 | print "%s{%s}" % ( ','.join( selectors ), ''.join(['%s:%s;' % (key, properties[key]) for key in porder])[:-1] ) |
139 | 140 | ||
140 | return css | 141 | return css |
141 | 142 | ||
142 | 143 | ||
143 | def compressCSS (self, css): | 144 | def compressCSS (self, css): |
144 | self.log("compressing CSS") | 145 | self.log("compressing CSS") |
145 | #return self.regexCssCompressor(css) | 146 | #return self.regexCssCompressor(css) |
146 | return self.cssminCompressor(css) | 147 | return self.cssminCompressor(css) |
147 | 148 | ||
148 | 149 | ||
149 | #========================================================================== | 150 | #========================================================================== |
150 | 151 | ||
151 | def compressJS_jsmin (self, js, description): | 152 | def compressJS_jsmin (self, js, description): |
152 | self.log("compressing " + description + " code") | 153 | self.log("compressing " + description + " code") |
153 | original = StringIO.StringIO(js) | 154 | original = StringIO.StringIO(js) |
154 | output = StringIO.StringIO() | 155 | output = StringIO.StringIO() |
155 | 156 | ||
156 | jsMinifier = jsmin.JavascriptMinify() | 157 | jsMinifier = jsmin.JavascriptMinify() |
157 | jsMinifier.minify(original, output) | 158 | jsMinifier.minify(original, output) |
158 | 159 | ||
159 | result = output.getvalue() | 160 | result = output.getvalue() |
160 | 161 | ||
161 | original.close() | 162 | original.close() |
162 | output.close() | 163 | output.close() |
163 | 164 | ||
164 | return result | 165 | return result |
165 | 166 | ||
166 | def compressJS_closureCompiler (self, js, description): | 167 | def compressJS_closureCompiler (self, js, description): |
167 | #Googles Closure compiler | 168 | #Googles Closure compiler |
168 | #java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js | 169 | #java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js |
169 | 170 | ||
170 | result = js | 171 | result = js |
171 | 172 | ||
172 | return result | 173 | return result |
173 | 174 | ||
174 | 175 | ||
175 | def compressJS (self, js, description): | 176 | def compressJS (self, js, description): |
176 | return self.compressJS_jsmin(js, description) | 177 | return self.compressJS_jsmin(js, description) |
177 | #return self.compressJS_closureCompiler(js, description) | 178 | #return self.compressJS_closureCompiler(js, description) |
178 | 179 | ||
179 | 180 | ||
180 | #========================================================================== | 181 | #========================================================================== |
181 | 182 | ||
182 | def packBookmarklet (self, bookmakeletCode, version): | 183 | def packBookmarklet (self, bookmakeletCode, version): |
183 | replacers = [ | 184 | replacers = [ |
184 | ('isLoginForm', 'ilf'), | 185 | ('isLoginForm', 'ilf'), |
185 | ('findLoginForm', 'flf'), | 186 | ('findLoginForm', 'flf'), |
186 | ('findLoginForm', 'flf'), | 187 | ('findLoginForm', 'flf'), |
187 | ('formParameters', 'fp' ), | 188 | ('formParameters', 'fp' ), |
188 | ('pageParameters', 'pp' ), | 189 | ('pageParameters', 'pp' ), |
189 | ('serializeJSON', 'sj' ), | 190 | ('serializeJSON', 'sj' ), |
190 | ('reprString', 'rs' ), | 191 | ('reprString', 'rs' ), |
191 | ('logFormParameters', 'lfp'), | 192 | ('logFormParameters', 'lfp'), |
192 | ('loadClipperzBookmarklet','lcb'), | 193 | ('loadClipperzBookmarklet','lcb'), |
193 | ('loginForm', 'lf' ), | 194 | ('loginForm', 'lf' ), |
194 | ('parameters', 'p' ), | 195 | ('parameters', 'p' ), |
195 | ('inputElementValues', 'iev'), | 196 | ('inputElementValues', 'iev'), |
196 | ] | 197 | ] |
197 | result = self.compressJS(bookmakeletCode, version + " bookmarklet") | 198 | result = self.compressJS(bookmakeletCode, version + " bookmarklet") |
198 | 199 | ||
199 | result = re.sub('\n', ' ', result) #Fit all in a single line | 200 | result = re.sub('\n', ' ', result) #Fit all in a single line |
200 | # result = re.sub('\s+', ' ', result) #Collapse "redundant" spaces. WARNING: this could have some evil side effects on constant strings used inside to code!! | 201 | # result = re.sub('\s+', ' ', result) #Collapse "redundant" spaces. WARNING: this could have some evil side effects on constant strings used inside to code!! |
201 | # result = re.sub('\s?([,\+=\(\)\{\};])\s?', '\\1', result) | 202 | # result = re.sub('\s?([,\+=\(\)\{\};])\s?', '\\1', result) |
202 | 203 | ||
203 | for replacer in replacers: | 204 | for replacer in replacers: |
204 | result = re.sub(replacer[0], replacer[1], result) | 205 | result = re.sub(replacer[0], replacer[1], result) |
205 | 206 | ||
206 | # <!-- escaping required to handle the bookmarklet code within the javascript code --> | 207 | # <!-- escaping required to handle the bookmarklet code within the javascript code --> |
207 | result = re.sub('\://', '%3a%2f%2f',result) | 208 | result = re.sub('\://', '%3a%2f%2f',result) |
208 | result = re.sub('/', '%2f', result) | 209 | result = re.sub('/', '%2f', result) |
209 | # result = re.sub('"', '%22', result) | 210 | # result = re.sub('"', '%22', result) |
210 | result = re.sub('"', '\\"', result) | 211 | result = re.sub('"', '\\"', result) |
211 | result = re.sub('\"', '%22', result) | 212 | result = re.sub('\"', '%22', result) |
212 | result = re.sub('\'', '%22', result) | 213 | result = re.sub('\'', '%22', result) |
213 | result = re.sub('\\\\', '%5c', result) | 214 | result = re.sub('\\\\', '%5c', result) |
214 | result = result.strip() | 215 | result = result.strip() |
215 | result = 'javascript:' + result | 216 | result = 'javascript:' + result |
216 | 217 | ||
217 | # replacers = [ | 218 | # replacers = [ |
218 | # ('aForm', '_1' ), | 219 | # ('aForm', '_1' ), |
219 | # ('inputFields', '_2' ), | 220 | # ('inputFields', '_2' ), |
220 | # ('passwordFieldsFound','_3' ), | 221 | # ('passwordFieldsFound','_3' ), |
221 | # ('aDocument', '_6' ), | 222 | # ('aDocument', '_6' ), |
222 | # ('aLevel', '_7' ), | 223 | # ('aLevel', '_7' ), |
223 | # # ('result', '_8' ), | 224 | # # ('result', '_8' ), |
224 | # ('documentForms', '_9' ), | 225 | # ('documentForms', '_9' ), |
225 | # ('iFrames', '_c' ), | 226 | # ('iFrames', '_c' ), |
226 | # ('anInputElement', '_d' ), | 227 | # ('anInputElement', '_d' ), |
227 | # ('options', '_f' ), | 228 | # ('options', '_f' ), |
228 | # ('option', '_12'), | 229 | # ('option', '_12'), |
229 | # ('aLoginForm', '_13'), | 230 | # ('aLoginForm', '_13'), |
230 | # # ('action', '_17'), | 231 | # # ('action', '_17'), |
231 | # ('radioValues', '_18'), | 232 | # ('radioValues', '_18'), |
232 | # ('radioValueName', '_19'), | 233 | # ('radioValueName', '_19'), |
233 | # ('inputElement', '_1a'), | 234 | # ('inputElement', '_1a'), |
234 | # ('elementValues', '_1b'), | 235 | # ('elementValues', '_1b'), |
235 | # ('radioValue', '_1c'), | 236 | # ('radioValue', '_1c'), |
236 | # ('values', '_1d'), | 237 | # ('values', '_1d'), |
237 | # ('objtype', '_21'), | 238 | # ('objtype', '_21'), |
238 | # ('useKey', '_27'), | 239 | # ('useKey', '_27'), |
239 | # ('bookmarkletDiv', '_28'), | 240 | # ('bookmarkletDiv', '_28'), |
240 | # ('someParameters', '_29'), | 241 | # ('someParameters', '_29'), |
241 | # ('anException', '_2a'), | 242 | # ('anException', '_2a'), |
242 | # ('newDiv', '_2b'), | 243 | # ('newDiv', '_2b'), |
243 | # ('base_url', '_2c'), | 244 | # ('base_url', '_2c'), |
244 | # ('help_url', '_2d'), | 245 | # ('help_url', '_2d'), |
245 | # ('logo_image_url', '_2e'), | 246 | # ('logo_image_url', '_2e'), |
246 | # ('background_image_url','_2f'), | 247 | # ('background_image_url','_2f'), |
247 | # ('close_image_url', '_30'), | 248 | # ('close_image_url', '_30'), |
248 | # #('bookmarklet_textarea','_31'), | 249 | # #('bookmarklet_textarea','_31'), |
249 | # ('innerHTML', '_32'), | 250 | # ('innerHTML', '_32'), |
250 | # ] | 251 | # ] |
251 | # for replacer in replacers: | 252 | # for replacer in replacers: |
252 | # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result) | 253 | # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result) |
253 | 254 | ||
254 | # replacers = [ | 255 | # replacers = [ |
255 | # ('headNode', '_1' ), | 256 | # ('headNode', '_1' ), |
256 | # ('clipperzScriptNode','_2' ), | 257 | # ('clipperzScriptNode','_2' ), |
257 | # ] | 258 | # ] |
258 | # for replacer in replacers: | 259 | # for replacer in replacers: |
259 | # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result) | 260 | # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result) |
260 | 261 | ||
261 | # result = re.sub(';', ';\n', result) | 262 | # result = re.sub(';', ';\n', result) |
262 | 263 | ||
263 | return result | 264 | return result |
264 | 265 | ||
265 | 266 | ||
266 | 267 | ||
267 | def bookmarklet (self): | 268 | def bookmarklet (self): |
268 | cacheKey = 'bookmarklet' | 269 | cacheKey = 'bookmarklet' |
269 | if not self.processedFiles.has_key(cacheKey): | 270 | if not self.processedFiles.has_key(cacheKey): |
270 | result = 'bookmarklet="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet.js']), "regular") + '";bookmarklet_ie="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet_IE.js']), "IE") + '";' | 271 | result = 'bookmarklet="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet.js']), "regular") + '";bookmarklet_ie="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet_IE.js']), "IE") + '";' |
271 | self.processedFiles[cacheKey] = result | 272 | self.processedFiles[cacheKey] = result |
272 | else: | 273 | else: |
273 | result = self.processedFiles[cacheKey] | 274 | result = self.processedFiles[cacheKey] |
274 | 275 | ||
275 | return result | 276 | return result |
276 | 277 | ||
277 | 278 | ||
278 | def replaceTemplatePlaceholders (self, pageTitle, copyright, css, code, jsLoadMode, version, versionType): | 279 | def replaceTemplatePlaceholders (self, pageTitle, copyright, css, code, jsLoadMode, version, versionType): |
279 | result = self.template() | 280 | result = self.template() |
280 | 281 | ||
281 | result = result.replace('@page.title@', pageTitle, 1) | 282 | result = result.replace('@page.title@', pageTitle, 1) |
282 | result = result.replace('@copyright@', copyright, 1) | 283 | result = result.replace('@copyright@', copyright, 1) |
283 | result = result.replace('@css@', css, 1) | 284 | result = result.replace('@css@', css, 1) |
284 | #result = result.replace('@bookmarklet@', bookmarklet,1) | 285 | #result = result.replace('@bookmarklet@', bookmarklet,1) |
285 | result = result.replace('@application.version@', version, 1) | 286 | result = result.replace('@application.version@', version, 1) |
286 | result = result.replace('@application.version.type@', versionType,1) | 287 | result = result.replace('@application.version.type@', versionType,1) |
287 | result = result.replace('@js_' + jsLoadMode + '@', code, 1) | 288 | result = result.replace('@js_' + jsLoadMode + '@', code, 1) |
288 | 289 | ||
289 | result = re.sub('@js_[^@]+@', '', result) | 290 | result = re.sub('@js_[^@]+@', '', result) |
290 | 291 | ||
291 | return result | 292 | return result |
292 | 293 | ||
293 | 294 | ||
294 | def assembleCopyrightHeader (self): | 295 | def assembleCopyrightHeader (self): |
295 | processedFile = 'copyright' | 296 | processedFile = 'copyright' |
296 | if not self.processedFiles.has_key(processedFile): | 297 | if not self.processedFiles.has_key(processedFile): |
297 | #self.log("assembling copyright header") | 298 | #self.log("assembling copyright header") |
298 | copyrightValues = self.settings['copyright.values'] | 299 | copyrightValues = self.settings['copyright.values'] |
299 | license = self.loadFilesContent('../../properties', ['license.txt']) | 300 | license = self.loadFilesContent('../../properties', ['license.txt']) |
300 | result = self.loadFilesContent('properties', ['creditsAndCopyrights.txt']) | 301 | result = self.loadFilesContent('properties', ['creditsAndCopyrights.txt']) |
301 | 302 | ||
302 | result = re.sub('@clipperz.license@', license, result) | 303 | result = re.sub('@clipperz.license@', license, result) |
303 | for key in copyrightValues: | 304 | for key in copyrightValues: |
304 | result = re.sub('@'+key+'@', copyrightValues[key], result) | 305 | result = re.sub('@'+key+'@', copyrightValues[key], result) |
305 | 306 | ||
306 | self.processedFiles[processedFile] = result | 307 | self.processedFiles[processedFile] = result |
307 | 308 | ||
308 | return self.processedFiles[processedFile] | 309 | return self.processedFiles[processedFile] |
309 | 310 | ||
310 | 311 | ||
311 | def cssTagsForFiles (self, basePath, files): | 312 | def cssTagsForFiles (self, basePath, files): |
312 | #<link rel="stylesheet" type="text/css" href="./css/reset-min.css" /> | 313 | #<link rel="stylesheet" type="text/css" href="./css/reset-min.css" /> |
313 | return '\n'.join(map(lambda file: '<link rel="stylesheet" type="text/css" href="' + basePath + '/' + file + '" />', files)) | 314 | return '\n'.join(map(lambda file: '<link rel="stylesheet" type="text/css" href="' + basePath + '/' + file + '" />', files)) |
314 | 315 | ||
315 | 316 | ||
316 | def cssTagForContent (self, content): | 317 | def cssTagForContent (self, content): |
317 | return '<style type="text/css">' + content + '</style>' | 318 | return '<style type="text/css">' + content + '</style>' |
318 | 319 | ||
319 | 320 | ||
320 | def scriptTagsForFiles (self, basePath, files): | 321 | def scriptTagsForFiles (self, basePath, files): |
321 | #<script type='text/javascript' src='./js/src/bookmarklet.js'></script> | 322 | #<script type='text/javascript' src='./js/src/bookmarklet.js'></script> |
322 | return '\n'.join(map(lambda file: '<script type="text/javascript" src="' + basePath + '/' + file + '"></script>', files)) | 323 | return '\n'.join(map(lambda file: '<script type="text/javascript" src="' + basePath + '/' + file + '" charset="utf-8"></script>', files)) |
323 | 324 | ||
324 | 325 | ||
325 | def scriptTagForContent (self, content): | 326 | def scriptTagForContent (self, content): |
326 | return '<script>' + content + '</script>' | 327 | return '<script>' + content + '</script>' |
327 | 328 | ||
328 | 329 | ||
329 | def assembleVersion (self, pageTitle, copyright, css, js, jsLoadMode, version, versionType): | 330 | def assembleVersion (self, pageTitle, copyright, css, js, jsLoadMode, version, versionType): |
330 | cacheKey = version + "-" + versionType | 331 | cacheKey = version + "-" + versionType |
331 | if not self.processedFiles.has_key(cacheKey): | 332 | if not self.processedFiles.has_key(cacheKey): |
332 | result = self.replaceTemplatePlaceholders(pageTitle, copyright, css, js, jsLoadMode, version, versionType) | 333 | result = self.replaceTemplatePlaceholders(pageTitle, copyright, css, js, jsLoadMode, version, versionType) |
333 | self.processedFiles[cacheKey] = result | 334 | self.processedFiles[cacheKey] = result |
334 | else: | 335 | else: |
335 | result = self.processedFiles[cacheKey] | 336 | result = self.processedFiles[cacheKey] |
336 | 337 | ||
337 | #self.log("# cacheKey:\n" + result) | 338 | #self.log("# cacheKey:\n" + result) |
338 | return result | 339 | return result |
339 | 340 | ||
340 | 341 | ||
341 | def assemble (self, assemblyMode='INSTALL', versionType='LIVE'): | 342 | def assemble (self, assemblyMode='INSTALL', versionType='LIVE'): |
342 | 343 | ||
343 | if versionType == 'LIVE': | 344 | if versionType == 'LIVE': |
344 | pageTitle = "Clipperz - " + self.module | 345 | pageTitle = "Clipperz - " + self.module |
345 | else: | 346 | else: |
346 | pageTitle = "Clipperz - " + self.module + " [" + versionType + " - " + assemblyMode +"]" | 347 | pageTitle = "Clipperz - " + self.module + " [" + versionType + " - " + assemblyMode +"]" |
347 | 348 | ||
348 | if assemblyMode == 'INSTALL': | 349 | if assemblyMode == 'INSTALL': |
349 | copyright = self.assembleCopyrightHeader() | 350 | copyright = self.assembleCopyrightHeader() |
350 | css =self.cssTagForContent(self.compressCSS(self.loadFilesContent('css', self.settings['css']))) | 351 | css =self.cssTagForContent(self.compressCSS(self.loadFilesContent('css', self.settings['css']))) |
351 | js =self.scriptTagForContent( | 352 | js =self.scriptTagForContent( |
352 | self.bookmarklet() + | 353 | self.bookmarklet() + |
353 | '\n' + | 354 | '\n' + |
354 | self.compressJS(self.loadFilesContent('js', self.settings['js']), "application") | 355 | self.compressJS(self.loadFilesContent('js', self.settings['js']), "application") |
355 | ) | 356 | ) |
356 | jsLoadMode = 'EMBEDDED' | 357 | jsLoadMode = 'EMBEDDED' |
357 | 358 | ||
358 | elif assemblyMode == 'DEBUG': | 359 | elif assemblyMode == 'DEBUG': |
359 | copyright = self.assembleCopyrightHeader() | 360 | copyright = self.assembleCopyrightHeader() |
360 | css =self.cssTagsForFiles('./css', self.filterFiles(self.settings['css'])) | 361 | css =self.cssTagsForFiles('./css', self.filterFiles(self.settings['css'])) |
361 | js =self.scriptTagForContent(self.bookmarklet()) + \ | 362 | js =self.scriptTagForContent(self.bookmarklet()) + \ |
362 | '\n' + \ | 363 | '\n' + \ |
363 | self.scriptTagsForFiles('./js', self.filterFiles(self.settings['js'])) | 364 | self.scriptTagsForFiles('./js', self.filterFiles(self.settings['js'])) |
364 | jsLoadMode = 'LINKED' | 365 | jsLoadMode = 'LINKED' |
365 | 366 | ||
366 | elif assemblyMode == 'DEVELOPMENT': | 367 | elif assemblyMode == 'DEVELOPMENT': |
367 | copyright = "" | 368 | copyright = "" |
368 | css =self.cssTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'css')), self.filterFiles(self.settings['css'])) | 369 | css =self.cssTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'css')), self.filterFiles(self.settings['css'])) |
369 | js =self.scriptTagForContent(self.bookmarklet()) + \ | 370 | js =self.scriptTagForContent(self.bookmarklet()) + \ |
370 | '\n' + \ | 371 | '\n' + \ |
371 | self.scriptTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'js')), self.filterFiles(self.settings['js'])) | 372 | self.scriptTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'js')), self.filterFiles(self.settings['js'])) |
372 | jsLoadMode = 'LINKED' | 373 | jsLoadMode = 'LINKED' |
373 | 374 | ||
374 | else: | 375 | else: |
375 | raise NotImplementedError() | 376 | raise NotImplementedError() |
376 | 377 | ||
377 | return self.assembleVersion( | 378 | return self.assembleVersion( |
378 | pageTitle = pageTitle, | 379 | pageTitle = pageTitle, |
379 | copyright = copyright, | 380 | copyright = copyright, |
380 | css = css, | 381 | css = css, |
381 | js = js, | 382 | js = js, |
382 | jsLoadMode = jsLoadMode, | 383 | jsLoadMode = jsLoadMode, |
383 | version = self.repositoryVersion, | 384 | version = self.repositoryVersion, |
384 | versionType = versionType | 385 | versionType = versionType |
385 | ) | 386 | ) |
386 | 387 | ||
387 | 388 | ||
388 | 389 | ||
389 | 390 | ||
diff --git a/scripts/builder/repository.py b/scripts/builder/repository.py index 0efa10b..0045de7 100644 --- a/scripts/builder/repository.py +++ b/scripts/builder/repository.py | |||
@@ -1,77 +1,81 @@ | |||
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | # -*- coding: UTF-8 -*- | 2 | # -*- coding: UTF-8 -*- |
3 | 3 | ||
4 | 4 | ||
5 | def repositoryWithPath (path): | 5 | def repositoryWithPath (path): |
6 | try: | 6 | try: |
7 | from git import Repo | ||
8 | |||
9 | repo = Repo(path) | ||
10 | result = GitRepository(repo, path) | ||
11 | except ImportError: | ||
12 | print "Failed to import git, please install http://gitorious.org/git-python" | ||
13 | except: | ||
14 | from mercurial import ui, hg | 7 | from mercurial import ui, hg |
15 | 8 | ||
16 | repo = hg.repository(ui.ui(), path) | 9 | repo = hg.repository(ui.ui(), path) |
17 | result = HgRepository(repo, path) | 10 | result = HgRepository(repo, path) |
11 | except: | ||
12 | try: | ||
13 | from git import Repo | ||
14 | |||
15 | repo = Repo(path) | ||
16 | result = GitRepository(repo, path) | ||
17 | except ImportError, exception: | ||
18 | print "Failed to import git, please install http://gitorious.org/git-python" | ||
19 | raise exception | ||
20 | |||
18 | 21 | ||
19 | return result | 22 | return result |
20 | 23 | ||
21 | 24 | ||
22 | #=================================================================== | 25 | #=================================================================== |
23 | 26 | ||
24 | 27 | ||
25 | class Repository(object): | 28 | class Repository(object): |
26 | 29 | ||
27 | def __init__ (self, repository, path): | 30 | def __init__ (self, repository, path): |
28 | self.repository = repository | 31 | self.repository = repository |
29 | self.path = path | 32 | self.path = path |
30 | 33 | ||
31 | 34 | ||
32 | def revision (self): | 35 | def revision (self): |
33 | raise NotImplementedError() | 36 | raise NotImplementedError() |
34 | 37 | ||
35 | 38 | ||
36 | def areTherePendingChanges (self): | 39 | def areTherePendingChanges (self): |
37 | raise NotImplementedError() | 40 | raise NotImplementedError() |
38 | 41 | ||
39 | 42 | ||
40 | def version (self): | 43 | def version (self): |
41 | result = self.revision() | 44 | result = self.revision() |
42 | if self.areTherePendingChanges(): | 45 | if self.areTherePendingChanges(): |
43 | result = '>>> ' + result + ' <<<' | 46 | result = '>>> ' + result + ' <<<' |
44 | 47 | ||
45 | # print "VERSION: " + result | 48 | # print "VERSION: " + result |
46 | return result | 49 | return result |
47 | 50 | ||
48 | 51 | ||
49 | #=================================================================== | 52 | #=================================================================== |
50 | 53 | ||
51 | 54 | ||
52 | class GitRepository(Repository): | 55 | class GitRepository(Repository): |
56 | #http://gitorious.org/git-python | ||
53 | 57 | ||
54 | def revision (self): | 58 | def revision (self): |
55 | return self.repository.head.commit.hexsha | 59 | return self.repository.head.commit.hexsha |
56 | 60 | ||
57 | 61 | ||
58 | def areTherePendingChanges (self): | 62 | def areTherePendingChanges (self): |
59 | return self.repository.is_dirty() | 63 | return self.repository.is_dirty() |
60 | 64 | ||
61 | 65 | ||
62 | #=================================================================== | 66 | #=================================================================== |
63 | 67 | ||
64 | 68 | ||
65 | class HgRepository(Repository): | 69 | class HgRepository(Repository): |
66 | #http://mercurial.selenic.com/wiki/MercurialApi | 70 | #http://mercurial.selenic.com/wiki/MercurialApi |
67 | 71 | ||
68 | def revision (self): | 72 | def revision (self): |
69 | return 'hg:' + str(self.repository['tip']) | 73 | return 'hg:' + str(self.repository['tip']) |
70 | 74 | ||
71 | 75 | ||
72 | def areTherePendingChanges (self): | 76 | def areTherePendingChanges (self): |
73 | # TODO: FIXME: repository.status() does not report 'unknown(?)' files. :( | 77 | # TODO: FIXME: repository.status() does not report 'unknown(?)' files. :( |
74 | return not all(map(lambda fileList: len(fileList) == 0, self.repository.status())) | 78 | return not all(map(lambda fileList: len(fileList) == 0, self.repository.status())) |
75 | 79 | ||
76 | 80 | ||
77 | #=================================================================== | 81 | #=================================================================== |