Dart 2 update for pkg:jael

This commit is contained in:
Tobe O 2018-11-02 20:16:03 -04:00
parent 4abfc0a582
commit 4a77c6982d
16 changed files with 168 additions and 60 deletions

View file

@ -1,2 +1,3 @@
analyzer:
strong-mode: true
strong-mode:
implicit-casts: false

0
angel_jael/mono_pkg.yaml Normal file
View file

View file

@ -1,17 +1,17 @@
name: angel_jael
version: 1.0.3
version: 2.0.0
description: Angel support for the Jael templating engine.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/jael/tree/master/jael
environment:
sdk: ">=1.19.0 <=2.0.0"
sdk: ">=2.0.0-dev <=3.0.0"
dependencies:
angel_framework: ^1.0.0-dev
angel_framework: ^2.0.0-alpha
code_buffer: ^1.0.0
file: ^2.0.0
file: ^5.0.0
jael: ^1.0.0-alpha
jael_preprocessor: ^1.0.0-alpha
symbol_table: ^1.0.0
symbol_table: ^2.0.0
dev_dependencies:
angel_test: ^1.1.0-alpha
test: ^0.12.0
angel_test: ^2.0.0-alpha
test: ^1.0.0

View file

@ -1,5 +1,9 @@
# 2.0.0
* Dart 2 updates.
* Remove usage of `package:dart2_constant`.
# 1.0.6+1
* Ensure `<element>` pass attributes.
* Ensure `<element>` passes attributes.
# 1.0.6
* Add `index-as` to `for-each`.

View file

@ -1,5 +1,5 @@
import 'dart:convert';
import 'package:code_buffer/code_buffer.dart';
import 'package:dart2_constant/convert.dart';
import 'package:symbol_table/symbol_table.dart';
import 'ast/ast.dart';
import 'text/parser.dart';
@ -54,8 +54,8 @@ class Renderer {
buf
..writeln('<li>')
..indent()
..writeln('<b>$type:</b> ${error.span.start.toolString}: ${error
.message}')
..writeln(
'<b>$type:</b> ${error.span.start.toolString}: ${error.message}')
..writeln('<br>')
..writeln(
'<span style="color: red;">' +

View file

@ -68,8 +68,10 @@ class Parser {
StringLiteral implicitString() {
if (next(TokenType.string)) {
return prefixParselets[TokenType.string].parse(this, _current) as StringLiteral;
} /*else if (next(TokenType.text)) {
return prefixParselets[TokenType.string].parse(this, _current)
as StringLiteral;
}
/*else if (next(TokenType.text)) {
}*/
@ -264,8 +266,7 @@ class Parser {
if (tagName2.name != tagName.name) {
errors.add(new JaelError(
JaelErrorSeverity.error,
'Mismatched closing tags. Expected "${tagName.span
.text}"; got "${tagName2.name}" instead.',
'Mismatched closing tags. Expected "${tagName.span.text}"; got "${tagName2.name}" instead.',
lt2.span));
return null;
}

0
jael/mono_pkg.yaml Normal file
View file

View file

@ -1,16 +1,15 @@
name: jael
version: 1.0.6+1
version: 2.0.0
description: A simple server-side HTML templating engine for Dart.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/jael/tree/master/jael
environment:
sdk: ">=1.19.0 <=2.0.0"
sdk: ">=2.0.0-dev <=3.0.0"
dependencies:
charcode: ^1.0.0
code_buffer: ^1.0.0
dart2_constant: ^1.0.0
source_span: ^1.0.0
string_scanner: ^1.0.0
symbol_table: ^1.0.0
symbol_table: ^2.0.0
dev_dependencies:
test: ^0.12.0
test: ^1.0.0

View file

@ -18,13 +18,16 @@ void main() {
var html = render(template, {'sqrt': sqrt});
print(html);
expect(html, '''
expect(
html,
'''
<div>
<div>
The square root of 16 is 4.
</div>
</div>
'''.trim());
'''
.trim());
});
test('render into explicit tag name', () {
@ -40,13 +43,16 @@ void main() {
var html = render(template, {'sqrt': sqrt});
print(html);
expect(html, '''
expect(
html,
'''
<div>
<span>
The square root of 16 is 4.
</span>
</div>
'''.trim());
'''
.trim());
});
test('pass attributes', () {
@ -62,13 +68,16 @@ void main() {
var html = render(template, {'sqrt': sqrt});
print(html);
expect(html, '''
expect(
html,
'''
<div>
<div foo="bar" baz="quux">
The square root of 16 is 4.
</div>
</div>
'''.trim());
'''
.trim());
});
test('render without tag name', () {
@ -84,12 +93,15 @@ void main() {
var html = render(template, {'sqrt': sqrt});
print(html);
expect(html, '''
expect(
html,
'''
<div>
The square root of 16 is 4.
</div>
'''.trim());
'''
.trim());
});
}

View file

@ -21,7 +21,7 @@ main() {
try {
document = jael.parseDocument(template, sourceUrl: 'test.jl');
scope = new SymbolTable(values: {
scope = new SymbolTable<dynamic>(values: {
'csrf_token': 'foo',
'profile': {
'avatar': 'thosakwe.png',
@ -67,7 +67,7 @@ main() {
var buf = new CodeBuffer();
//jael.scan(template, sourceUrl: 'test.jl').tokens.forEach(print);
var document = jael.parseDocument(template, sourceUrl: 'test.jl');
var scope = new SymbolTable(values: {
var scope = new SymbolTable<dynamic>(values: {
'pokemon': const _Pokemon('Darkrai', 'Dark'),
});
@ -107,7 +107,7 @@ main() {
var buf = new CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jl');
var scope = new SymbolTable(values: {
var scope = new SymbolTable<dynamic>(values: {
'starters': starters,
});
@ -152,7 +152,7 @@ main() {
var buf = new CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jl');
var scope = new SymbolTable(values: {
var scope = new SymbolTable<dynamic>(values: {
'starters': starters,
});
@ -300,7 +300,7 @@ main() {
var buf = new CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jl');
var scope = new SymbolTable(values: {
var scope = new SymbolTable<dynamic>(values: {
'account': new _Account(isDisabled: true),
});
@ -327,7 +327,7 @@ main() {
var buf = new CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jl');
var scope = new SymbolTable(values: {
var scope = new SymbolTable<dynamic>(values: {
'account': new _Account(isDisabled: null),
});

View file

@ -83,7 +83,8 @@ main() {
<script aria-label="script">
window.alert('a string');
</script>
'''.trim(),
'''
.trim(),
sourceUrl: 'test.jl',
).tokens;
tokens.forEach(print);

View file

@ -1,2 +1,3 @@
analyzer:
strong-mode: true
strong-mode:
implicit-casts: false

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:collection';
import 'package:file/file.dart';
import 'package:jael/jael.dart';
import 'package:symbol_table/symbol_table.dart';
/// Modifies a Jael document.
typedef FutureOr<Document> Patcher(Document document,
@ -18,6 +19,7 @@ Future<Document> resolve(Document document, Directory currentDirectory,
// Resolve all includes...
var includesResolved =
await resolveIncludes(document, currentDirectory, onError);
var patched =
await applyInheritance(includesResolved, currentDirectory, onError);
@ -68,26 +70,63 @@ Future<Document> applyInheritance(Document document, Directory currentDirectory,
// by filling in blocks.
document = chain.removeFirst();
var blocks = new SymbolTable<Element>();
while (chain.isNotEmpty) {
var child = chain.removeFirst();
var blocks = extractBlockDeclarations(child.root, onError);
var scope = blocks;
extractBlockDeclarations(scope, child.root, onError);
var blocksExpanded =
await expandBlocks(document.root, blocks, currentDirectory, onError);
if (blocksExpanded == null) {
// This in itself is a block; expand it.
// TODO: Ambiguous
}
document =
new Document(child.doctype ?? document.doctype, blocksExpanded);
}
// Fill in any remaining blocks
var blocksExpanded =
await expandBlocks(document.root, {}, currentDirectory, onError);
await expandBlocks(document.root, blocks, currentDirectory, onError);
return new Document(document.doctype, blocksExpanded);
}
}
List<Element> allBlocksRecursive(Element element) {
var out = <Element>[];
for (var e in element.children) {
if (e is Element && e.tagName.name == 'block') {
out.add(e);
}
}
for (var child in element.children) {
if (child is Element) {
var childBlocks = allBlocksRecursive(child);
out.addAll(childBlocks);
//
// if (childBlocks.isNotEmpty) {
// print('<<<\n${child.span.highlight()}');
//
// for (var b in childBlocks) {
// print('!!!!\n${b.span.highlight()}');
// }
// }
}
}
return out; //out.reversed.toList();
}
/// Extracts any `block` declarations.
Map<String, Element> extractBlockDeclarations(
Element element, void onError(JaelError error)) {
Map<String, Element> blocks = {};
void extractBlockDeclarations(SymbolTable<Element> blocks, Element element,
void onError(JaelError error)) {
//var blockElements = allBlocksRecursive(element);
var blockElements =
element.children.where((e) => e is Element && e.tagName.name == 'block');
@ -104,11 +143,9 @@ Map<String, Element> extractBlockDeclarations(
nameAttr.span));
} else {
var name = (nameAttr.value as StringLiteral).value;
blocks[name] = blockElement;
blocks.assign(name, blockElement);
}
}
return blocks;
}
/// Finds the name of the parent template.
@ -134,8 +171,10 @@ String getParent(Document document, void onError(JaelError error)) {
}
/// Replaces any `block` tags within the element.
Future<Element> expandBlocks(Element element, Map<String, Element> blocks,
Future<Element> expandBlocks(Element element, SymbolTable<Element> blockss,
Directory currentDirectory, void onError(JaelError error)) async {
var blocks = blockss.createChild();
if (element is SelfClosingElement)
return element;
else if (element is RegularElement) {
@ -166,10 +205,11 @@ Future<Element> expandBlocks(Element element, Map<String, Element> blocks,
var name = (nameAttr.value as StringLiteral).value;
Iterable<ElementChild> children;
if (!blocks.containsKey(name)) {
if (blocks.resolve(name) == null) {
print('Hm what? $name');
children = child.children;
} else {
children = blocks[name].children;
children = blocks.resolve(name).value.children;
}
expanded.addAll(children);
@ -184,21 +224,62 @@ Future<Element> expandBlocks(Element element, Map<String, Element> blocks,
}
// Resolve all includes...
expanded = await Future.wait(expanded.map((c) {
if (c is! Element) return new Future.value(c);
return expandBlocks(c, blocks, currentDirectory, onError);
}));
var out = <ElementChild>[];
return new RegularElement(
for (var c in expanded) {
if (c is Element) {
var blocksExpanded =
await expandBlocks(c, blocks, currentDirectory, onError);
var nameAttr = c.attributes
.firstWhere((a) => a.name == 'name', orElse: () => null);
var name = (nameAttr?.value is StringLiteral)
? ((nameAttr.value as StringLiteral).value)
: null;
if (name == null) {
out.add(blocksExpanded);
} else {
// This element itself resolved to a block; expand it.
out.addAll(blocks.resolve(name)?.value?.children ?? <ElementChild>[]);
}
} else {
out.add(c);
}
}
var finalElement = new RegularElement(
element.lt,
element.tagName,
element.attributes,
element.gt,
expanded,
out,
element.lt2,
element.slash,
element.tagName2,
element.gt2);
// If THIS element is a block, it needs to be expanded as well.
if (element.tagName.name == 'block') {
var nameAttr = element.attributes
.firstWhere((a) => a.name == 'name', orElse: () => null);
if (nameAttr == null) {
onError(new JaelError(JaelErrorSeverity.warning,
'Missing "name" attribute in "block" tag.', element.span));
} else if (nameAttr.value is! StringLiteral) {
onError(new JaelError(
JaelErrorSeverity.warning,
'The "name" attribute in an "block" tag must be a string literal.',
nameAttr.span));
}
var name = (nameAttr.value as StringLiteral).value;
print('def $name');
blockss.assign(name, finalElement);
return null;
} else {
return finalElement;
}
} else {
throw new UnsupportedError(
'Unsupported element type: ${element.runtimeType}');

View file

View file

@ -6,7 +6,7 @@ homepage: https://github.com/angel-dart/jael/tree/master/jael_processor
environment:
sdk: ">=1.19.0 <=2.0.0"
dependencies:
file: ^2.0.0
file: ^5.0.0
jael: ^1.0.0-alpha
dev_dependencies:
test: ^0.12.0

View file

@ -29,11 +29,19 @@ main() {
// e.jl
fileSystem.file('e.jl').writeAsStringSync(
'<extend src="c.jl"><block name="greeting">Angel <block name="name">default</block></block></extend>');
'<extend src="c.jl"><block name="greeting">Angel <b><block name="name">default</block></b></block></extend>');
// e.jl
fileSystem.file('f.jl').writeAsStringSync(
'<extend src="e.jl"><block name="name">framework</block></extend>');
// fox.jl
fileSystem.file('fox.jl').writeAsStringSync(
'<block name="dance">The name is <block name="name"></block></block>');
// trot.jl
fileSystem.file('trot.jl').writeAsStringSync(
'<extend src="fox.jl"><block name="name">CONGA <i><block name="exclaim">YEAH</block></i></block></extend>');
// foxtrot.jl
fileSystem.file('foxtrot.jl').writeAsStringSync(
'<extend src="trot.jl"><block name="exclaim">framework</block></extend>');
});
test('blocks are replaced or kept', () async {
@ -87,7 +95,7 @@ main() {
});
test('blocks within blocks', () async {
var file = fileSystem.file('f.jl');
var file = fileSystem.file('foxtrot.jl');
var original = jael.parseDocument(await file.readAsString(),
sourceUrl: file.uri, onError: (e) => throw e);
var processed = await jael.resolve(