Dart 2 update for pkg:jael
This commit is contained in:
parent
4abfc0a582
commit
4a77c6982d
16 changed files with 168 additions and 60 deletions
|
@ -1,2 +1,3 @@
|
|||
analyzer:
|
||||
strong-mode: true
|
||||
strong-mode:
|
||||
implicit-casts: false
|
0
angel_jael/mono_pkg.yaml
Normal file
0
angel_jael/mono_pkg.yaml
Normal 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
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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;">' +
|
||||
|
|
|
@ -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
0
jael/mono_pkg.yaml
Normal 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
|
|
@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
});
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ main() {
|
|||
<script aria-label="script">
|
||||
window.alert('a string');
|
||||
</script>
|
||||
'''.trim(),
|
||||
'''
|
||||
.trim(),
|
||||
sourceUrl: 'test.jl',
|
||||
).tokens;
|
||||
tokens.forEach(print);
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
analyzer:
|
||||
strong-mode: true
|
||||
strong-mode:
|
||||
implicit-casts: false
|
|
@ -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}');
|
||||
|
|
0
jael_preprocessor/mono_pkg.yaml
Normal file
0
jael_preprocessor/mono_pkg.yaml
Normal 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
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue