diff --git a/angel_jael/analysis_options.yaml b/angel_jael/analysis_options.yaml index 518eb901..eae1e42a 100644 --- a/angel_jael/analysis_options.yaml +++ b/angel_jael/analysis_options.yaml @@ -1,2 +1,3 @@ analyzer: - strong-mode: true \ No newline at end of file + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/angel_jael/mono_pkg.yaml b/angel_jael/mono_pkg.yaml new file mode 100644 index 00000000..e69de29b diff --git a/angel_jael/pubspec.yaml b/angel_jael/pubspec.yaml index a12ca66a..adbc28d2 100644 --- a/angel_jael/pubspec.yaml +++ b/angel_jael/pubspec.yaml @@ -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 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 \ No newline at end of file + angel_test: ^2.0.0-alpha + test: ^1.0.0 diff --git a/jael/CHANGELOG.md b/jael/CHANGELOG.md index 8d4bca78..ce38a408 100644 --- a/jael/CHANGELOG.md +++ b/jael/CHANGELOG.md @@ -1,5 +1,9 @@ +# 2.0.0 +* Dart 2 updates. +* Remove usage of `package:dart2_constant`. + # 1.0.6+1 -* Ensure `` pass attributes. +* Ensure `` passes attributes. # 1.0.6 * Add `index-as` to `for-each`. diff --git a/jael/lib/src/renderer.dart b/jael/lib/src/renderer.dart index 910af96d..1e6c8d68 100644 --- a/jael/lib/src/renderer.dart +++ b/jael/lib/src/renderer.dart @@ -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('
  • ') ..indent() - ..writeln('$type: ${error.span.start.toolString}: ${error - .message}') + ..writeln( + '$type: ${error.span.start.toolString}: ${error.message}') ..writeln('
    ') ..writeln( '' + diff --git a/jael/lib/src/text/parser.dart b/jael/lib/src/text/parser.dart index 5f8de467..8e457058 100644 --- a/jael/lib/src/text/parser.dart +++ b/jael/lib/src/text/parser.dart @@ -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; } diff --git a/jael/mono_pkg.yaml b/jael/mono_pkg.yaml new file mode 100644 index 00000000..e69de29b diff --git a/jael/pubspec.yaml b/jael/pubspec.yaml index 8f4c7899..70a3967d 100644 --- a/jael/pubspec.yaml +++ b/jael/pubspec.yaml @@ -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 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 \ No newline at end of file + test: ^1.0.0 \ No newline at end of file diff --git a/jael/test/render/custom_element_test.dart b/jael/test/render/custom_element_test.dart index 08aef101..2546b34f 100644 --- a/jael/test/render/custom_element_test.dart +++ b/jael/test/render/custom_element_test.dart @@ -18,13 +18,16 @@ void main() { var html = render(template, {'sqrt': sqrt}); print(html); - expect(html, ''' + expect( + html, + '''
    The square root of 16 is 4.
    - '''.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, + '''
    The square root of 16 is 4.
    - '''.trim()); + ''' + .trim()); }); test('pass attributes', () { @@ -62,13 +68,16 @@ void main() { var html = render(template, {'sqrt': sqrt}); print(html); - expect(html, ''' + expect( + html, + '''
    The square root of 16 is 4.
    - '''.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, + '''
    The square root of 16 is 4.
    - '''.trim()); + ''' + .trim()); }); } diff --git a/jael/test/render/render_test.dart b/jael/test/render/render_test.dart index 2515d395..d10e4bc6 100644 --- a/jael/test/render/render_test.dart +++ b/jael/test/render/render_test.dart @@ -21,7 +21,7 @@ main() { try { document = jael.parseDocument(template, sourceUrl: 'test.jl'); - scope = new SymbolTable(values: { + scope = new SymbolTable(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(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(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(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(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(values: { 'account': new _Account(isDisabled: null), }); diff --git a/jael/test/text/scan_test.dart b/jael/test/text/scan_test.dart index 080aace7..7632d8d2 100644 --- a/jael/test/text/scan_test.dart +++ b/jael/test/text/scan_test.dart @@ -83,7 +83,8 @@ main() { -'''.trim(), +''' + .trim(), sourceUrl: 'test.jl', ).tokens; tokens.forEach(print); diff --git a/jael_preprocessor/analysis_options.yaml b/jael_preprocessor/analysis_options.yaml index 518eb901..eae1e42a 100644 --- a/jael_preprocessor/analysis_options.yaml +++ b/jael_preprocessor/analysis_options.yaml @@ -1,2 +1,3 @@ analyzer: - strong-mode: true \ No newline at end of file + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/jael_preprocessor/lib/jael_preprocessor.dart b/jael_preprocessor/lib/jael_preprocessor.dart index 260d9313..9f89323a 100644 --- a/jael_preprocessor/lib/jael_preprocessor.dart +++ b/jael_preprocessor/lib/jael_preprocessor.dart @@ -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 Patcher(Document document, @@ -18,6 +19,7 @@ Future 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 applyInheritance(Document document, Directory currentDirectory, // by filling in blocks. document = chain.removeFirst(); + var blocks = new SymbolTable(); + 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 allBlocksRecursive(Element element) { + var out = []; + + 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 extractBlockDeclarations( - Element element, void onError(JaelError error)) { - Map blocks = {}; +void extractBlockDeclarations(SymbolTable 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 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 expandBlocks(Element element, Map blocks, +Future expandBlocks(Element element, SymbolTable 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 expandBlocks(Element element, Map blocks, var name = (nameAttr.value as StringLiteral).value; Iterable 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 expandBlocks(Element element, Map 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 = []; - 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 ?? []); + } + } 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}'); diff --git a/jael_preprocessor/mono_pkg.yaml b/jael_preprocessor/mono_pkg.yaml new file mode 100644 index 00000000..e69de29b diff --git a/jael_preprocessor/pubspec.yaml b/jael_preprocessor/pubspec.yaml index 70b111e1..2355ac85 100644 --- a/jael_preprocessor/pubspec.yaml +++ b/jael_preprocessor/pubspec.yaml @@ -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 \ No newline at end of file diff --git a/jael_preprocessor/test/block_test.dart b/jael_preprocessor/test/block_test.dart index b91edb90..2cb16cc4 100644 --- a/jael_preprocessor/test/block_test.dart +++ b/jael_preprocessor/test/block_test.dart @@ -29,11 +29,19 @@ main() { // e.jl fileSystem.file('e.jl').writeAsStringSync( - 'Angel default'); + 'Angel default'); - // e.jl - fileSystem.file('f.jl').writeAsStringSync( - 'framework'); + // fox.jl + fileSystem.file('fox.jl').writeAsStringSync( + 'The name is '); + + // trot.jl + fileSystem.file('trot.jl').writeAsStringSync( + 'CONGA YEAH'); + + // foxtrot.jl + fileSystem.file('foxtrot.jl').writeAsStringSync( + 'framework'); }); 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(