91dd628bd8
Need unique name for library collision with template parser. Few more changes to work under VM. More changes for lang.dart seperation. Seperation from lang.dart (tokenizer can't access private fields of base class in another library). This was allowed in frog but not in the VM. VM is right so need to sever dependency. BUG= TEST= Review URL: https://chromiumcodereview.appspot.com//9695048 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5544 260f80e4-7a28-3924-810f-c04153c831b5
573 lines
15 KiB
Dart
573 lines
15 KiB
Dart
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#import('dart:html');
|
|
#import('template.dart');
|
|
#import('../lib/file_system_memory.dart');
|
|
|
|
String currSampleTemplate;
|
|
|
|
void changeTemplate() {
|
|
final Document doc = window.document;
|
|
final SelectElement samples = doc.query('#templateSamples');
|
|
final TextAreaElement template = doc.query('#template');
|
|
template.value = sample(samples.value);
|
|
}
|
|
|
|
String sample(String sampleName) {
|
|
final String each = '\${#each';
|
|
final String endEach = '\${/each}';
|
|
final String with = '\${#with';
|
|
final String endWith = '\${/with}';
|
|
|
|
final String simpleTemplate = '''
|
|
template NameEntry(String name, int age) {
|
|
<div var=topDiv attr="test" attr1=test1 attr2='test2' attr3=test3>
|
|
<span var=spanElem>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
final String simpleTemplate2 = '''
|
|
template NameEntry(String name, int age) {
|
|
<div var=topDiv attr="test" attr1=test1 attr2='test2' attr3=test3>
|
|
<h1>
|
|
<h2>
|
|
<h3>
|
|
<span var=spanElem>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</h3>
|
|
</h2>
|
|
</h1>
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
final String simpleTemplateCSS = '''
|
|
template NameEntry(String name, int age) {
|
|
css {
|
|
.foo {
|
|
left: 10px;
|
|
}
|
|
}
|
|
<div var=topDiv attr="test" attr1=test1 attr2='test2' attr3=test3>
|
|
<span var=spanElem>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
|
|
final String eachTemplate = '''
|
|
template Applications(var products) {
|
|
<div>
|
|
${each} products}
|
|
<div>
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${users}</span>
|
|
</div>
|
|
${endEach}
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
final String withTemplate = '''
|
|
template Product(Person person) {
|
|
<div>
|
|
${with} person}
|
|
<div>
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
${endWith}
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
final String withTemplate2 = '''
|
|
template Product(Person person) {
|
|
<div>
|
|
<span var=a1>
|
|
<h1>
|
|
${with} person}
|
|
<div>
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
${endWith}
|
|
</h1>
|
|
</span>
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
final String complexTemplate = '''
|
|
template ProductsForPerson(Person person, var products) {
|
|
<div>
|
|
${with} person}
|
|
<div>
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
${each} products}
|
|
<div>
|
|
<span>product=\${name},users=\${users}</span>
|
|
</div>
|
|
${endEach}
|
|
${endWith}
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
final String complexTemplate2 = '''
|
|
template ProductsForPerson(Person person, var products) {
|
|
<div>
|
|
${with} person}
|
|
<div>
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
<div>
|
|
${each} products}
|
|
<span>product=\${name},users=\${users}</span>
|
|
${endEach}
|
|
</div>
|
|
${endWith}
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
final String complexTemplate3 = '''
|
|
template ProductsForPerson(Person person, var products) {
|
|
css {
|
|
.sales-item {
|
|
font-family: arial;
|
|
background-color: lightgray;
|
|
margin-left: 10px;
|
|
border-bottom: 1px solid white;
|
|
}
|
|
.ytd-sales {
|
|
position: absolute;
|
|
left: 100px;
|
|
}
|
|
}
|
|
<div>
|
|
${with} person}
|
|
<div>
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
<div>
|
|
${each} products}
|
|
<div>product=\${name},users=\${users}</div>
|
|
${each} products.sales}
|
|
<div class="sales-item">
|
|
<span>\${country}</span>
|
|
<span class="ytd-sales">\\\$\${yearly}</span>
|
|
</div>
|
|
${endEach}
|
|
${endEach}
|
|
</div>
|
|
${endWith}
|
|
</div>
|
|
}
|
|
|
|
|
|
template NameEntry(String name, int age) {
|
|
css {
|
|
.name-item {
|
|
font-size: 18pt;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
<div var=topDiv class="name-item" attr="test" attr1=test1 attr2='test2' attr3=test3>
|
|
<span var=spanElem>\${name}</span>
|
|
<span> - </span>
|
|
<span>\${age}</span>
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
// Test #each in a #each where the nested #each is a top-level child of the
|
|
// outer #each.
|
|
final String complexTemplate4 = '''
|
|
template DivisionSales(var divisions) {
|
|
<div>
|
|
\${#each divisions}
|
|
<div>
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${id}</span>
|
|
</div>
|
|
<div>
|
|
\${#each divisions.products}
|
|
<div>
|
|
<span var=productItem>▶</span>
|
|
<span>Product</span>
|
|
<span>\${name}</span>
|
|
<span>\${users} users</span>
|
|
</div>
|
|
\${#each products.sales}
|
|
<div>
|
|
<span>\${country}</span>
|
|
<span>\\\$\${yearly}</span>
|
|
</div>
|
|
\${/each}
|
|
\${/each}
|
|
</div>
|
|
\${/each}
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
|
|
final String realWorldList = '''
|
|
template DivisionSales(var divisions) {
|
|
css {
|
|
.division-item {
|
|
background-color: #bbb;
|
|
border-top: 2px solid white;
|
|
line-height: 20pt;
|
|
padding-left: 5px;
|
|
}
|
|
.product-item {
|
|
background-color: lightgray;
|
|
margin-left: 10px;
|
|
border-top: 2px solid white;
|
|
line-height: 20pt;
|
|
}
|
|
.product-title {
|
|
position: absolute;
|
|
left: 45px;
|
|
}
|
|
.product-name {
|
|
font-weight: bold;
|
|
position: absolute;
|
|
left: 100px;
|
|
}
|
|
.product-users {
|
|
position: absolute;
|
|
left: 150px;
|
|
font-style: italic;
|
|
color: gray;
|
|
width: 110px;
|
|
}
|
|
.expand-collapse {
|
|
margin-left: 5px;
|
|
margin-right: 5px;
|
|
vertical-align: top;
|
|
cursor: pointer;
|
|
}
|
|
.expand {
|
|
font-size: 9pt;
|
|
}
|
|
.collapse {
|
|
font-size: 8pt;
|
|
}
|
|
.show-sales {
|
|
display: inherit;
|
|
}
|
|
.hide-sales {
|
|
display: none;
|
|
}
|
|
.sales-item {
|
|
font-family: arial;
|
|
background-color: lightgray;
|
|
margin-left: 10px;
|
|
border-top: 1px solid white;
|
|
line-height: 18pt;
|
|
padding-left: 5px;
|
|
}
|
|
.ytd-sales {
|
|
position: absolute;
|
|
left: 100px;
|
|
}
|
|
}
|
|
<div>
|
|
\${#each divisions}
|
|
<div class="division-item">
|
|
<span>\${name}</span>
|
|
<span>-</span>
|
|
<span>\${id}</span>
|
|
</div>
|
|
<div>
|
|
\${#each divisions.products}
|
|
<div class="product-item">
|
|
<span var=productZippy class="expand-collapse expand">▼</span>
|
|
<span class='product-title'>Product</span>
|
|
<span class="product-name">\${name}</span>
|
|
<span class="product-users" align=right>\${users} users</span>
|
|
<div class="show-sales">
|
|
\${#each products.sales}
|
|
<div class="sales-item">
|
|
<span>\${country}</span>
|
|
<span class="ytd-sales">\\\$\${yearly}</span>
|
|
</div>
|
|
\${/each}
|
|
</div>
|
|
</div>
|
|
\${/each}
|
|
</div>
|
|
\${/each}
|
|
</div>
|
|
}
|
|
|
|
template Header(String company, Date date) {
|
|
css {
|
|
.header {
|
|
background-color: slateGray;
|
|
font-family: arial;
|
|
color: lightgray;
|
|
font-weight: bold;
|
|
padding-top: 20px;
|
|
}
|
|
}
|
|
<div class='header' align=center>
|
|
<h2>\${company}</h2>
|
|
<div align=right>\${date}</div>
|
|
</div>
|
|
}
|
|
''';
|
|
|
|
switch (sampleName) {
|
|
case "simple":
|
|
return simpleTemplate;
|
|
case "simple2":
|
|
return simpleTemplate2;
|
|
case "simpleCSS":
|
|
return simpleTemplateCSS;
|
|
case "with":
|
|
return withTemplate;
|
|
case "with2":
|
|
return withTemplate2;
|
|
case "list":
|
|
return eachTemplate;
|
|
case "complex":
|
|
return complexTemplate;
|
|
case "complex2":
|
|
return complexTemplate2;
|
|
case "complex3":
|
|
return complexTemplate3;
|
|
case "complex4":
|
|
return complexTemplate4;
|
|
case "realWorldList":
|
|
return realWorldList;
|
|
default:
|
|
print("ERROR: Unknown sample template");
|
|
}
|
|
}
|
|
|
|
void runTemplate([bool debug = false, bool parseOnly = false]) {
|
|
final Document doc = window.document;
|
|
final TextAreaElement dartClass = doc.query("#dart");
|
|
final TextAreaElement template = doc.query('#template');
|
|
final TableCellElement validity = doc.query('#validity');
|
|
final TableCellElement result = doc.query('#result');
|
|
|
|
bool templateValid = true;
|
|
StringBuffer dumpTree = new StringBuffer();
|
|
StringBuffer code = new StringBuffer();
|
|
String htmlTemplate = template.value;
|
|
|
|
if (debug) {
|
|
try {
|
|
List<Template> templates = templateParseAndValidate(htmlTemplate);
|
|
for (var tmpl in templates) {
|
|
dumpTree.add(tmpl.toDebugString());
|
|
}
|
|
|
|
// Generate the Dart class(es) for all template(s).
|
|
// Pass in filename of 'foo' for testing in UITest.
|
|
code.add(Codegen.generate(templates, 'foo'));
|
|
} catch (final htmlException) {
|
|
// TODO(terry): TBD
|
|
print("ERROR unhandled EXCEPTION");
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (!debug) {
|
|
try {
|
|
cssParseAndValidate(cssExpr, cssWorld);
|
|
} catch (final cssException) {
|
|
templateValid = false;
|
|
dumpTree = cssException.toString();
|
|
}
|
|
} else if (parseOnly) {
|
|
try {
|
|
Parser parser = new Parser(new lang.SourceFile(
|
|
lang.SourceFile.IN_MEMORY_FILE, cssExpr));
|
|
Stylesheet stylesheet = parser.parse();
|
|
StringBuffer stylesheetTree = new StringBuffer();
|
|
String prettyStylesheet = stylesheet.toString();
|
|
stylesheetTree.add("${prettyStylesheet}\n");
|
|
stylesheetTree.add("\n============>Tree Dump<============\n");
|
|
stylesheetTree.add(stylesheet.toDebugString());
|
|
dumpTree = stylesheetTree.toString();
|
|
} catch (final cssParseException) {
|
|
templateValid = false;
|
|
dumpTree = cssParseException.toString();
|
|
}
|
|
} else {
|
|
try {
|
|
dumpTree = cssParseAndValidateDebug(cssExpr, cssWorld);
|
|
} catch (final cssException) {
|
|
templateValid = false;
|
|
dumpTree = cssException.toString();
|
|
}
|
|
}
|
|
*/
|
|
|
|
final bgcolor = templateValid ? "white" : "red";
|
|
final color = templateValid ? "black" : "white";
|
|
final valid = templateValid ? "VALID" : "NOT VALID";
|
|
String resultStyle = "resize: none; margin: 0; height: 100%; width: 100%;"
|
|
"padding: 5px 7px;";
|
|
|
|
result.innerHTML = '''
|
|
<textarea style="${resultStyle}">${dumpTree.toString()}</textarea>
|
|
''';
|
|
|
|
dartClass.value = code.toString();
|
|
}
|
|
|
|
void main() {
|
|
final element = new Element.tag('div');
|
|
|
|
element.innerHTML = '''
|
|
<table style="width: 100%; height: 100%;">
|
|
<tbody>
|
|
<tr>
|
|
<td style="vertical-align: top; width: 50%; padding-right: 7px;">
|
|
<table style="height: 100%; width: 100%;" cellspacing=0 cellpadding=0 border=0>
|
|
<tbody>
|
|
<tr style="vertical-align: top; height: 1em;">
|
|
<td>
|
|
<span style="font-weight:bold;">Generated Dart</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<textarea id="dart" style="resize: none; width: 100%; height: 100%; padding: 5px 7px;"></textarea>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
<td>
|
|
<table style="width: 100%; height: 100%;" cellspacing=0 cellpadding=0 border=0>
|
|
<tbody>
|
|
<tr style="vertical-align: top; height: 50%;">
|
|
<td>
|
|
<table style="width: 100%; height: 100%;" cellspacing=0 cellpadding=0 border=0>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
<span style="font-weight:bold;">HTML Template</span>
|
|
</td>
|
|
</tr>
|
|
<tr style="height: 100%;">
|
|
<td>
|
|
<textarea id="template" style="resize: none; width: 100%; height: 100%; padding: 5px 7px;">${sample("simple")}</textarea>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr style="vertical-align: top; height: 50px;">
|
|
<td>
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
<button id=generate>Generate</button>
|
|
</td>
|
|
<td align="right">
|
|
<select id=templateSamples>
|
|
<option value="simple">Simple Template</option>
|
|
<option value="simple2">Simple Template #2</option>
|
|
<option value="simpleCSS">Simple Template w/ CSS</option>
|
|
<option value="with">With Template</option>
|
|
<option value="with2">With Template #2</option>
|
|
<option value="list">List Template</option>
|
|
<option value="complex">Complex Template</option>
|
|
<option value="complex2">Complex Template #2</option>
|
|
<option value="complex3">Complex Template #3 w/ CSS</option>
|
|
<option value="complex4">Complex Template #4</option>
|
|
<option value="realWorldList">Real world</option>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr style="vertical-align: top;">
|
|
<td>
|
|
<table style="width: 100%; height: 100%;" border="0" cellpadding="0" cellspacing="0">
|
|
<tbody>
|
|
<tr style="vertical-align: top; height: 1em;">
|
|
<td>
|
|
<span style="font-weight:bold;">Parse Tree</span>
|
|
</td>
|
|
</tr>
|
|
<tr style="vertical-align: top; height: 1em;">
|
|
<td id="validity">
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td id="result">
|
|
<textarea style="resize: none; width: 100%; height: 100%; border: black solid 1px; padding: 5px 7px;"></textarea>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
''';
|
|
|
|
document.body.style.setProperty("background-color", "lightgray");
|
|
document.body.elements.add(element);
|
|
|
|
ButtonElement genElem = window.document.query('#generate');
|
|
genElem.on.click.add((MouseEvent e) {
|
|
runTemplate(true, true);
|
|
});
|
|
|
|
SelectElement cannedTemplates = window.document.query('#templateSamples');
|
|
cannedTemplates.on.change.add((e) {
|
|
changeTemplate();
|
|
});
|
|
|
|
parseOptions([], null);
|
|
initHtmlWorld(false);
|
|
|
|
// Don't display any colors in the UI.
|
|
options.useColors = false;
|
|
|
|
// Replace error handler bring up alert for any problems.
|
|
world.printHandler = (String msg) {
|
|
window.alert(msg);
|
|
};
|
|
}
|