Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: client/tools/htmlconverter.py

Issue 9567032: Bring htmlconverter back up to date: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | client/tools/htmlconverter_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 # for details. All rights reserved. Use of this source code is governed by a 2 # for details. All rights reserved. Use of this source code is governed by a
3 # BSD-style license that can be found in the LICENSE file. 3 # BSD-style license that can be found in the LICENSE file.
4 4
5 #!/usr/bin/env python 5 #!/usr/bin/env python
6 # 6 #
7 7
8 """Rewrites HTML files, converting Dart script sections into JavaScript. 8 """Rewrites HTML files, converting Dart script sections into JavaScript.
9 9
10 Process HTML files, and internally changes script sections that use Dart code 10 Process HTML files, and internally changes script sections that use Dart code
(...skipping 12 matching lines...) Expand all
23 23
24 sys.path.append(TOOLS_PATH) 24 sys.path.append(TOOLS_PATH)
25 import utils 25 import utils
26 26
27 DART_MIME_TYPE = "application/dart" 27 DART_MIME_TYPE = "application/dart"
28 LIBRARY_PATTERN = "^#library\(.*\);" 28 LIBRARY_PATTERN = "^#library\(.*\);"
29 IMPORT_SOURCE_MATCHER = re.compile( 29 IMPORT_SOURCE_MATCHER = re.compile(
30 r"^ *(#import|#source)(\(['\"])([^'\"]*)(.*\);)", re.MULTILINE) 30 r"^ *(#import|#source)(\(['\"])([^'\"]*)(.*\);)", re.MULTILINE)
31 DOM_IMPORT_MATCHER = re.compile( 31 DOM_IMPORT_MATCHER = re.compile(
32 r"^#import\(['\"]dart\:dom['\"].*\);", re.MULTILINE) 32 r"^#import\(['\"]dart\:dom['\"].*\);", re.MULTILINE)
33 HTML_NO_PREFIX_IMPORT_MATCHER = re.compile( 33 HTML_IMPORT_MATCHER = re.compile(
34 r"^#import.*(dart:html|html.dart)['\"]\);", re.MULTILINE) 34 r"^#import\(['\"]dart\:html['\"].*\);", re.MULTILINE)
35 JSON_IMPORT_MATCHER = re.compile(
36 r"^#import\(['\"]dart:json['\"].*\);", re.MULTILINE)
37
38 DARTC_NOT_FOUND_ERROR = (
39 """Couldn't find compiler: please run the following commands:
40 $ cd %s
41 $ ./tools/build.py --arch=ia32""")
42 35
43 FROG_NOT_FOUND_ERROR = ( 36 FROG_NOT_FOUND_ERROR = (
44 """Couldn't find compiler: please run the following commands: 37 """Couldn't find compiler: please run the following commands:
45 $ cd %s/frog 38 $ cd %s/frog
46 $ ./tools/build.py -m release""") 39 $ ./tools/build.py -m release""")
47 40
48 ENTRY_POINT = """ 41 ENTRY_POINT_DOM = """
49 #library('entry'); 42 #library('entry');
50 #import('dart:dom'); 43 #import('dart:dom');
51 #import('%s', prefix: 'original'); 44 #import('%s', prefix: 'original');
52 main() { 45 main() {
53 window.addEventListener('DOMContentLoaded', (e) => original.main(), false); 46 window.addEventListener('DOMContentLoaded', (e) => original.main(), false);
54 } 47 }
55 """ 48 """
56 49
50 ENTRY_POINT_HTML = """
51 #library('entry');
52 #import('dart:html');
53 #import('%s', prefix: 'original');
54 main() {
55 window.on.contentLoaded.add((e) => original.main());
56 }
57 """
58
57 CSS_TEMPLATE = '<style type="text/css">%s</style>' 59 CSS_TEMPLATE = '<style type="text/css">%s</style>'
58 CHROMIUM_SCRIPT_TEMPLATE = '<script type="application/javascript">%s</script>' 60 CHROMIUM_SCRIPT_TEMPLATE = '<script type="application/javascript">%s</script>'
59 61
60 DARTIUM_TO_JS_SCRIPT = """ 62 DARTIUM_TO_JS_SCRIPT = """
61 <script type="text/javascript"> 63 <script type="text/javascript">
62 (function() { 64 (function() {
63 // Let the user know that Dart is required. 65 // Let the user know that Dart is required.
64 if (!document.implementation.hasFeature('Dart')) { 66 if (!window.navigator.webkitStartDart) {
65 if (confirm( 67 if (confirm(
66 "You are trying to run Dart code on a browser " + 68 "You are trying to run Dart code on a browser " +
67 "that doesn't support Dart. Do you want to redirect to " + 69 "that doesn't support Dart. Do you want to redirect to " +
68 "a version compiled to JavaScript instead?")) { 70 "a version compiled to JavaScript instead?")) {
69 var addr = window.location; 71 var addr = window.location;
70 window.location = addr.toString().replace('-dart.html', '-js.html'); 72 window.location = addr.toString().replace('-dart.html', '-js.html');
71 } 73 }
74 } else {
75 window.navigator.webkitStartDart();
72 } 76 }
73 })(); 77 })();
74 </script> 78 </script>
75 """ 79 """
76 80
77 def adjustImports(contents): 81 def adjustImports(contents):
78 def repl(matchobj): 82 def repl(matchobj):
79 path = matchobj.group(3) 83 path = matchobj.group(3)
80 if not path.startswith('dart:'): 84 if not path.startswith('dart:'):
81 path = abspath(path) 85 path = abspath(path)
82 return (matchobj.group(1) + matchobj.group(2) + path + matchobj.group(4)) 86 return (matchobj.group(1) + matchobj.group(2) + path + matchobj.group(4))
83 return IMPORT_SOURCE_MATCHER.sub(repl, contents) 87 return IMPORT_SOURCE_MATCHER.sub(repl, contents)
84 88
85 class DartCompiler(object): 89 class DartCompiler(object):
86 """ Common code for compiling Dart script tags in an HTML file. """ 90 """ Common code for compiling Dart script tags in an HTML file. """
87 91
88 def __init__(self, optimize=False, use_frog=False, verbose=False, 92 def __init__(self, verbose=False,
89 extra_flags=""): 93 extra_flags=""):
90 self.optimize = optimize
91 self.verbose = verbose 94 self.verbose = verbose
92 self.extra_flags = extra_flags 95 self.extra_flags = extra_flags
93 self.use_frog = use_frog
94 96
95 def compileCode(self, src=None, body=None): 97 def compileCode(self, src=None, body=None):
96 """ Compile the given source code. 98 """ Compile the given source code.
97 99
98 Either the script tag has a src attribute or a non-empty body (one of the 100 Either the script tag has a src attribute or a non-empty body (one of the
99 arguments will be none, the other is not). 101 arguments will be none, the other is not).
100 102
101 Args: 103 Args:
102 src: a string pointing to a Dart script file. 104 src: a string pointing to a Dart script file.
103 body: a string containing Dart code. 105 body: a string containing Dart code.
104 """ 106 """
105 107
106 outdir = tempfile.mkdtemp() 108 outdir = tempfile.mkdtemp()
107 indir = None 109 indir = None
110 useDartHtml = False
108 if src is not None: 111 if src is not None:
109 if body is not None and body.strip() != '': 112 if body is not None and body.strip() != '':
110 raise ConverterException( 113 raise ConverterException(
111 "The script body should be empty if src is specified") 114 "The script body should be empty if src is specified")
112 elif src.endswith('.dart'): 115 elif src.endswith('.dart'):
113 indir = tempfile.mkdtemp() 116 indir = tempfile.mkdtemp()
114 inputfile = abspath(src) 117 inputfile = abspath(src)
115 with open(inputfile, 'r') as f: 118 with open(inputfile, 'r') as f:
116 contents = f.read(); 119 contents = f.read();
117 120
121 if HTML_IMPORT_MATCHER.search(contents):
122 useDartHtml = True
123
118 # We will import the source file to emulate in JS that code is run after 124 # We will import the source file to emulate in JS that code is run after
119 # DOMContentLoaded. We need a #library to ensure #import won't fail: 125 # DOMContentLoaded. We need a #library to ensure #import won't fail:
120 if not re.search(LIBRARY_PATTERN, contents, re.MULTILINE): 126 if not re.search(LIBRARY_PATTERN, contents, re.MULTILINE):
121 inputfile = join(indir, 'code.dart') 127 inputfile = join(indir, 'code.dart')
122 with open(inputfile, 'w') as f: 128 with open(inputfile, 'w') as f:
123 f.write("#library('code');") 129 f.write("#library('code');")
124 f.write(adjustImports(contents)) 130 f.write(adjustImports(contents))
125 131
126 else: 132 else:
127 raise ConverterException("invalid file type:" + src) 133 raise ConverterException("invalid file type:" + src)
128 else: 134 else:
129 if body is None or body.strip() == '': 135 if body is None or body.strip() == '':
130 # nothing to do 136 # nothing to do
131 print 'Warning: empty script tag with no src attribute' 137 print 'Warning: empty script tag with no src attribute'
132 return '' 138 return ''
133 139
134 indir = tempfile.mkdtemp() 140 indir = tempfile.mkdtemp()
135 # eliminate leading spaces in front of directives 141 # eliminate leading spaces in front of directives
136 body = adjustImports(body) 142 body = adjustImports(body)
137 143
144 if HTML_IMPORT_MATCHER.search(body):
145 useDartHtml = True
146
138 inputfile = join(indir, 'code.dart') 147 inputfile = join(indir, 'code.dart')
139 with open(inputfile, 'w') as f: 148 with open(inputfile, 'w') as f:
140 f.write("#library('inlinedcode');\n") 149 f.write("#library('inlinedcode');\n")
141 # dom and json are added by default
142 if not DOM_IMPORT_MATCHER.search(body):
143 f.write("#import('dart:dom');\n")
144 if not JSON_IMPORT_MATCHER.search(body):
145 f.write("#import('dart:json');\n")
146 # html import will conflict with DOM import
147 if HTML_NO_PREFIX_IMPORT_MATCHER.search(body):
148 raise ConverterException(
149 'Can\'t import "dom:html" or "html.dart" from scripts inlined ' +
150 'in the page without a prefix. This import conflicts with an ' +
151 ' import of "dart:dom" that is injected automatically.')
152 f.write(body) 150 f.write(body)
153 151
152 if useDartHtml:
153 entryPoint = ENTRY_POINT_HTML
154 else:
155 entryPoint = ENTRY_POINT_DOM
156
154 wrappedfile = join(indir, 'entry.dart') 157 wrappedfile = join(indir, 'entry.dart')
155 with open(wrappedfile, 'w') as f: 158 with open(wrappedfile, 'w') as f:
156 f.write(ENTRY_POINT % inputfile) 159 f.write(entryPoint % inputfile)
157 160
158 status, out, err = execute(self.compileCommand(wrappedfile, outdir), 161 status, out, err = execute(self.compileCommand(wrappedfile, outdir),
159 self.verbose) 162 self.verbose)
160 if status: 163 if status:
161 raise ConverterException('compilation errors found by dartc') 164 raise ConverterException('compilation errors')
162 165
163 # Inline the compiled code in the page 166 # Inline the compiled code in the page
164 with open(self.outputFileName(wrappedfile, outdir), 'r') as f: 167 with open(self.outputFileName(wrappedfile, outdir), 'r') as f:
165 res = f.read() 168 res = f.read()
166 169
167 # Cleanup 170 # Cleanup
168 if indir is not None: 171 if indir is not None:
169 shutil.rmtree(indir) 172 shutil.rmtree(indir)
170 shutil.rmtree(outdir) 173 shutil.rmtree(outdir)
171 return CHROMIUM_SCRIPT_TEMPLATE % res 174 return CHROMIUM_SCRIPT_TEMPLATE % res
172 175
173 def compileCommand(self, inputfile, outdir): 176 def compileCommand(self, inputfile, outdir):
174 if not self.use_frog: 177 binary = abspath(join(DART_PATH,
175 binary = abspath(join(DART_PATH, 178 utils.GetBuildRoot(utils.GuessOS(),
176 # TODO(sigmund): support also mode = release 179 'release', 'ia32'),
177 utils.GetBuildRoot(utils.GuessOS(), 'debug', 'ia32'), 180 'frog', 'bin', 'frogsh'))
178 'dartc')) 181 if not exists(binary):
179 if not exists(binary): 182 raise ConverterException(FROG_NOT_FOUND_ERROR % DART_PATH)
180 raise ConverterException(DARTC_NOT_FOUND_ERROR % DART_PATH) 183
181 cmd = [binary, 184 cmd = [binary, '--compile-only',
182 '-noincremental', 185 '--libdir=' + join(DART_PATH, 'frog', 'lib'),
183 '--work', outdir, 186 '--out=' + self.outputFileName(inputfile, outdir)]
184 '--out', self.outputFileName(inputfile, outdir)]
185 if self.optimize:
186 cmd.append('--optimize')
187 else:
188 binary = abspath(join(DART_PATH,
189 utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32'),
190 'frog', 'bin', 'frogsh'))
191 if not exists(binary):
192 raise ConverterException(FROG_NOT_FOUND_ERROR % DART_PATH)
193 cmd = [binary, '--compile-only',
194 '--libdir=' + join(DART_PATH, 'frog', 'lib'),
195 '--out=' + self.outputFileName(inputfile, outdir)]
196 if self.extra_flags != "": 187 if self.extra_flags != "":
197 cmd.append(self.extra_flags); 188 cmd.append(self.extra_flags);
198 cmd.append(inputfile) 189 cmd.append(inputfile)
199 return cmd 190 return cmd
200 191
201 def outputFileName(self, inputfile, outdir): 192 def outputFileName(self, inputfile, outdir):
202 return join(outdir, basename(inputfile) + '.js') 193 return join(outdir, basename(inputfile) + '.js')
203 194
204 def execute(cmd, verbose=False): 195 def execute(cmd, verbose=False):
205 """Execute a command in a subprocess. """ 196 """Execute a command in a subprocess. """
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 if not exists(dirname): 466 if not exists(dirname):
476 raise 467 raise
477 468
478 class ConverterException(Exception): 469 class ConverterException(Exception):
479 """ An exception encountered during the convertion process """ 470 """ An exception encountered during the convertion process """
480 pass 471 pass
481 472
482 def Flags(): 473 def Flags():
483 """ Constructs a parser for extracting flags from the command line. """ 474 """ Constructs a parser for extracting flags from the command line. """
484 result = optparse.OptionParser() 475 result = optparse.OptionParser()
485 result.add_option("--optimize",
486 help="Use optimizer in dartc",
487 default=False,
488 action="store_true")
489 result.add_option("--frog",
490 help="Use the frog compiler",
491 default=False,
492 action="store_true")
493 result.add_option("--verbose", 476 result.add_option("--verbose",
494 help="Print verbose output", 477 help="Print verbose output",
495 default=False, 478 default=False,
496 action="store_true") 479 action="store_true")
497 result.add_option("-o", "--out", 480 result.add_option("-o", "--out",
498 help="Output directory", 481 help="Output directory",
499 type="string", 482 type="string",
500 default=None, 483 default=None,
501 action="store") 484 action="store")
502 result.add_option("-t", "--target", 485 result.add_option("-t", "--target",
(...skipping 21 matching lines...) Expand all
524 prefix_path = dirname(filename) 507 prefix_path = dirname(filename)
525 508
526 # outdirBase is the directory to place all subdirectories for other dart files 509 # outdirBase is the directory to place all subdirectories for other dart files
527 # and resources. 510 # and resources.
528 converter = DartToDartHTMLConverter(prefix_path, outdirBase, verbose) 511 converter = DartToDartHTMLConverter(prefix_path, outdirBase, verbose)
529 converter.feed(contents) 512 converter.feed(contents)
530 converter.close() 513 converter.close()
531 writeOut(converter.getResult(), outfile) 514 writeOut(converter.getResult(), outfile)
532 515
533 def convertForChromium( 516 def convertForChromium(
534 filename, optimize, use_frog, extra_flags, outfile, verbose): 517 filename, extra_flags, outfile, verbose):
535 """ Converts a file for a chromium target. """ 518 """ Converts a file for a chromium target. """
536 with open(filename, 'r') as f: 519 with open(filename, 'r') as f:
537 contents = f.read() 520 contents = f.read()
538 prefix_path = dirname(filename) 521 prefix_path = dirname(filename)
539 converter = DartHTMLConverter( 522 converter = DartHTMLConverter(
540 DartCompiler(optimize, use_frog, verbose, extra_flags), prefix_path) 523 DartCompiler(verbose, extra_flags), prefix_path)
541 converter.feed(contents) 524 converter.feed(contents)
542 converter.close() 525 converter.close()
543 writeOut(converter.getResult(), outfile) 526 writeOut(converter.getResult(), outfile)
544 527
545 def convertForOffline(filename, outfile, verbose, encode_images): 528 def convertForOffline(filename, outfile, verbose, encode_images):
546 """ Converts a file for offline use. """ 529 """ Converts a file for offline use. """
547 with codecs.open(filename, 'r', 'utf-8') as f: 530 with codecs.open(filename, 'r', 'utf-8') as f:
548 contents = f.read() 531 contents = f.read()
549 converter = OfflineHTMLConverter(dirname(filename), 532 converter = OfflineHTMLConverter(dirname(filename),
550 dirname(outfile), 533 dirname(outfile),
(...skipping 19 matching lines...) Expand all
570 return 1 553 return 1
571 554
572 try: 555 try:
573 filename = args[0] 556 filename = args[0]
574 extension = filename[filename.rfind('.'):] 557 extension = filename[filename.rfind('.'):]
575 if extension != '.html' and extension != '.htm': 558 if extension != '.html' and extension != '.htm':
576 print "Invalid input file extension: %s" % extension 559 print "Invalid input file extension: %s" % extension
577 return 1 560 return 1
578 outfile = join(options.out, filename) 561 outfile = join(options.out, filename)
579 if 'chromium' in options.target or 'js' in options.target: 562 if 'chromium' in options.target or 'js' in options.target:
580 convertForChromium(filename, options.optimize, 563 convertForChromium(filename,
581 options.frog, options.extra_flags, 564 options.extra_flags,
582 outfile.replace(extension, '-js' + extension), options.verbose) 565 outfile.replace(extension, '-js' + extension), options.verbose)
583 if 'dartium' in options.target: 566 if 'dartium' in options.target:
584 convertForDartium(filename, options.out, 567 convertForDartium(filename, options.out,
585 outfile.replace(extension, '-dart' + extension), options.verbose) 568 outfile.replace(extension, '-dart' + extension), options.verbose)
586 except Exception as e: 569 except Exception as e:
587 print "%sERROR%s: %s" % (RED_COLOR, NO_COLOR, str(e)) 570 print "%sERROR%s: %s" % (RED_COLOR, NO_COLOR, str(e))
588 return 1 571 return 1
589 return 0 572 return 0
590 573
591 if __name__ == '__main__': 574 if __name__ == '__main__':
592 sys.exit(main()) 575 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | client/tools/htmlconverter_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698