platform/angel_jael/lib/angel_jael.dart

105 lines
3.2 KiB
Dart
Raw Normal View History

2017-09-30 23:01:30 +00:00
import 'dart:convert';
import 'package:angel_framework/angel_framework.dart';
import 'package:code_buffer/code_buffer.dart';
import 'package:file/file.dart';
import 'package:jael/jael.dart';
import 'package:jael_preprocessor/jael_preprocessor.dart';
import 'package:symbol_table/symbol_table.dart';
2017-10-01 03:14:44 +00:00
/// Configures an Angel server to use Jael to render templates.
///
/// To enable "minified" output, you need to override the [createBuffer] function,
/// to instantiate a [CodeBuffer] that emits no spaces or line breaks.
2017-10-02 16:12:51 +00:00
///
/// To apply additional transforms to parsed documents, provide a set of [patch] functions.
2017-09-30 23:01:30 +00:00
AngelConfigurer jael(Directory viewsDirectory,
2017-10-02 16:12:51 +00:00
{String fileExtension, bool cacheViews: false, Iterable<Patcher> patch, CodeBuffer createBuffer()}) {
2017-10-01 03:14:44 +00:00
var cache = <String, Document>{};
2017-09-30 23:01:30 +00:00
fileExtension ??= '.jl';
createBuffer ??= () => new CodeBuffer();
return (Angel app) async {
app.viewGenerator = (String name, [Map locals]) async {
var errors = <JaelError>[];
2017-10-01 03:14:44 +00:00
Document processed;
if (cacheViews == true && cache.containsKey(name)) {
processed = cache[name];
} else {
var file = viewsDirectory.childFile(name + fileExtension);
var contents = await file.readAsString();
var doc =
parseDocument(contents, sourceUrl: file.uri, onError: errors.add);
processed = doc;
try {
2017-10-02 16:12:51 +00:00
processed = await resolve(doc, viewsDirectory, patch: patch, onError: errors.add);
2017-10-01 03:14:44 +00:00
} catch (_) {
// Ignore these errors, so that we can show syntax errors.
}
if (cacheViews == true) {
cache[name] = processed;
}
2017-09-30 23:01:30 +00:00
}
var buf = createBuffer();
var scope = new SymbolTable(values: locals ?? {});
if (errors.isEmpty) {
try {
const Renderer().render(processed, buf, scope);
return buf.toString();
} on JaelError catch (e) {
errors.add(e);
}
}
buf
..writeln('<!DOCTYPE html>')
..writeln('<html lang="en">')
..indent()
..writeln('<head>')
..indent()
..writeln(
'<meta name="viewport" content="width=device-width, initial-scale=1">',
)
..writeln('<title>${errors.length} Error(s)</title>')
..outdent()
..writeln('</head>')
..writeln('<body>')
..writeln('<h1>${errors.length} Error(s)</h1>')
..writeln('<ul>')
..indent();
for (var error in errors) {
var type =
error.severity == JaelErrorSeverity.warning ? 'warning' : 'error';
buf
..writeln('<li>')
..indent()
..writeln(
'<b>$type:</b> ${error.span.start.toolString}: ${error.message}')
..writeln('<br>')
..writeln(
'<span style="color: red;">' +
HTML_ESCAPE
.convert(error.span.highlight(color: false))
.replaceAll('\n', '<br>') +
'</span>',
)
..outdent()
..writeln('</li>');
}
buf
..outdent()
..writeln('</ul>')
..writeln('</body>')
..writeln('</html>');
return buf.toString();
};
};
}