diff --git a/packages/jael/.gitignore b/packages/jael/.gitignore new file mode 100644 index 00000000..37e7b7e6 --- /dev/null +++ b/packages/jael/.gitignore @@ -0,0 +1,51 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties diff --git a/packages/jael/.idea/misc.xml b/packages/jael/.idea/misc.xml new file mode 100644 index 00000000..639900d1 --- /dev/null +++ b/packages/jael/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/jael/.idea/modules.xml b/packages/jael/.idea/modules.xml new file mode 100644 index 00000000..d171efec --- /dev/null +++ b/packages/jael/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/jael/.idea/runConfigurations/blocks_within_blocks_in_block_test_dart.xml b/packages/jael/.idea/runConfigurations/blocks_within_blocks_in_block_test_dart.xml new file mode 100644 index 00000000..5032bd0a --- /dev/null +++ b/packages/jael/.idea/runConfigurations/blocks_within_blocks_in_block_test_dart.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/packages/jael/.idea/runConfigurations/for_loop_in_render_test_dart.xml b/packages/jael/.idea/runConfigurations/for_loop_in_render_test_dart.xml new file mode 100644 index 00000000..de242953 --- /dev/null +++ b/packages/jael/.idea/runConfigurations/for_loop_in_render_test_dart.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/packages/jael/.idea/runConfigurations/jael__example.xml b/packages/jael/.idea/runConfigurations/jael__example.xml new file mode 100644 index 00000000..5b6d4161 --- /dev/null +++ b/packages/jael/.idea/runConfigurations/jael__example.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/packages/jael/.idea/runConfigurations/main_dart.xml b/packages/jael/.idea/runConfigurations/main_dart.xml new file mode 100644 index 00000000..644077c1 --- /dev/null +++ b/packages/jael/.idea/runConfigurations/main_dart.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/packages/jael/.idea/runConfigurations/tests_in_dsx_test_dart.xml b/packages/jael/.idea/runConfigurations/tests_in_dsx_test_dart.xml new file mode 100644 index 00000000..9c1ec0de --- /dev/null +++ b/packages/jael/.idea/runConfigurations/tests_in_dsx_test_dart.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/packages/jael/.idea/runConfigurations/tests_in_jael.xml b/packages/jael/.idea/runConfigurations/tests_in_jael.xml new file mode 100644 index 00000000..b905e806 --- /dev/null +++ b/packages/jael/.idea/runConfigurations/tests_in_jael.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/packages/jael/.idea/vcs.xml b/packages/jael/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/packages/jael/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/jael/.travis.yml b/packages/jael/.travis.yml new file mode 100644 index 00000000..58ef8a07 --- /dev/null +++ b/packages/jael/.travis.yml @@ -0,0 +1,2 @@ +language: dart +script: bash ./travis.sh diff --git a/packages/jael/LICENSE b/packages/jael/LICENSE new file mode 100644 index 00000000..89074fd3 --- /dev/null +++ b/packages/jael/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 The Angel Framework + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/jael/README.md b/packages/jael/README.md new file mode 100644 index 00000000..d35c15f5 --- /dev/null +++ b/packages/jael/README.md @@ -0,0 +1,34 @@ +# jael +[![Pub](https://img.shields.io/pub/v/jael.svg)](https://pub.dartlang.org/packages/jael) +[![build status](https://travis-ci.org/angel-dart/jael.svg)](https://travis-ci.org/angel-dart/jael) + +A simple server-side HTML templating engine for Dart. + +Though its syntax is but a superset of HTML, it supports features such as: +* **Custom elements** +* Loops +* Conditionals +* Template inheritance +* Block scoping +* `switch` syntax +* Interpolation of any Dart expression + +Jael is a good choice for applications of any scale, especially when the development team is small, +or the time invested in building an SPA would be too much. + +## Documentation +Each of the [packages within this repository](#this-repository) contains +some sort of documentation. + +Documentation for Jael syntax and directives has been +**moved** to the +[Angel framework wiki](https://docs.angel-dart.dev/packages/front-end/jael). + +## This Repository +Within this repository are three packages: + +* `package:jael` - Contains the Jael parser, AST, and HTML renderer. +* `package:jael_preprocessor` - Handles template inheritance, and facilitates the use of "compile-time" constructs. +* `package:build_jael` - Uses `package:build` to compile Jael templates, therefore allowing speedy incremental builds to HTML files. +* `package:angel_jael` - [Angel](https://angel-dart.github.io) support for Jael. Angel contains other +facilities to speed up application development, so something like Jael is right at home. diff --git a/packages/jael/angel_jael/.gitignore b/packages/jael/angel_jael/.gitignore new file mode 100644 index 00000000..cab9622e --- /dev/null +++ b/packages/jael/angel_jael/.gitignore @@ -0,0 +1,16 @@ +# Created by .ignore support plugin (hsz.mobi) +### Dart template +# See https://www.dartlang.org/tools/private-files.html + +# Files and directories created by pub +.packages +.pub/ +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +.dart_tool \ No newline at end of file diff --git a/packages/jael/angel_jael/CHANGELOG.md b/packages/jael/angel_jael/CHANGELOG.md new file mode 100644 index 00000000..695b9be9 --- /dev/null +++ b/packages/jael/angel_jael/CHANGELOG.md @@ -0,0 +1,13 @@ +# 2.0.0 +* Angel 2 and Dart 2 updates. +* Default to `.jael` instead of `.jl`. + +# 1.0.3 +* Update for annoying map casting bug. + +# 1.0.2 +* Update for DSX support. +* Clear the buffer on errors. + +# 1.0.1 +* Use `Renderer.errorDocument`. \ No newline at end of file diff --git a/packages/jael/angel_jael/LICENSE b/packages/jael/angel_jael/LICENSE new file mode 100644 index 00000000..89074fd3 --- /dev/null +++ b/packages/jael/angel_jael/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 The Angel Framework + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/jael/angel_jael/README.md b/packages/jael/angel_jael/README.md new file mode 100644 index 00000000..0ac62b18 --- /dev/null +++ b/packages/jael/angel_jael/README.md @@ -0,0 +1,83 @@ +# jael +[![Pub](https://img.shields.io/pub/v/angel_jael.svg)](https://pub.dartlang.org/packages/angel_jael) +[![build status](https://travis-ci.org/angel-dart/jael.svg)](https://travis-ci.org/angel-dart/jael) + + +[Angel](https://angel-dart.github.io) +support for +[Jael](https://github.com/angel-dart/jael). + +# Installation +In your `pubspec.yaml`: + +```yaml +dependencies: + angel_jael: ^1.0.0-alpha +``` + +# Usage +Just like `mustache` and other renderers, configuring Angel to use +Jael is as simple as calling `app.configure`: + +```dart +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_jael/angel_jael.dart'; +import 'package:file/file.dart'; + +AngelConfigurer myPlugin(FileSystem fileSystem) { + return (Angel app) async { + // Connect Jael to your server... + await app.configure( + jael(fileSystem.directory('views')), + ); + }; +} +``` + +`package:angel_jael` supports caching views, to improve server performance. +You might not want to enable this in development, so consider setting +the flag to `app.isProduction`: + +``` +jael(viewsDirectory, cacheViews: app.isProduction); +``` + +Keep in mind that this package uses `package:file`, rather than +`dart:io`. + +The following is a basic example of a server setup that can render Jael +templates from a directory named `views`: + +```dart +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_jael/angel_jael.dart'; +import 'package:file/local.dart'; +import 'package:logging/logging.dart'; + +main() async { + var app = new Angel(); + var fileSystem = const LocalFileSystem(); + + await app.configure( + jael(fileSystem.directory('views')), + ); + + // Render the contents of views/index.jael + app.get('/', (res) => res.render('index', {'title': 'ESKETTIT'})); + + app.use(() => throw new AngelHttpException.notFound()); + + app.logger = new Logger('angel') + ..onRecord.listen((rec) { + print(rec); + if (rec.error != null) print(rec.error); + if (rec.stackTrace != null) print(rec.stackTrace); + }); + + var server = await app.startServer(null, 3000); + print('Listening at http://${server.address.address}:${server.port}'); +} +``` + +To apply additional transforms to parsed documents, provide a +set of `patch` functions, like in `package:jael_preprocessor`. \ No newline at end of file diff --git a/packages/jael/angel_jael/analysis_options.yaml b/packages/jael/angel_jael/analysis_options.yaml new file mode 100644 index 00000000..eae1e42a --- /dev/null +++ b/packages/jael/angel_jael/analysis_options.yaml @@ -0,0 +1,3 @@ +analyzer: + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/packages/jael/angel_jael/example/main.dart b/packages/jael/angel_jael/example/main.dart new file mode 100644 index 00000000..b77503dc --- /dev/null +++ b/packages/jael/angel_jael/example/main.dart @@ -0,0 +1,44 @@ +import 'dart:convert'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_framework/http.dart'; +import 'package:angel_jael/angel_jael.dart'; +import 'package:file/local.dart'; +import 'package:logging/logging.dart'; + +main() async { + var app = new Angel(); + var http = new AngelHttp(app); + var fileSystem = const LocalFileSystem(); + + await app.configure( + jael(fileSystem.directory('views')), + ); + + app.get( + '/', + (req, res) => + res.render('index', {'title': 'Sample App', 'message': null})); + + app.post('/', (req, res) async { + var body = await req.parseBody().then((_) => req.bodyAsMap); + print('Body: $body'); + var msg = body['message'] ?? ''; + return await res.render('index', { + 'title': 'Form Submission', + 'message': msg, + 'json_message': json.encode(msg), + }); + }); + + app.fallback((req, res) => throw new AngelHttpException.notFound()); + + app.logger = new Logger('angel') + ..onRecord.listen((rec) { + print(rec); + if (rec.error != null) print(rec.error); + if (rec.stackTrace != null) print(rec.stackTrace); + }); + + var server = await http.startServer('127.0.0.1', 3000); + print('Listening at http://${server.address.address}:${server.port}'); +} diff --git a/packages/jael/angel_jael/example/views/index.jael b/packages/jael/angel_jael/example/views/index.jael new file mode 100644 index 00000000..0555f063 --- /dev/null +++ b/packages/jael/angel_jael/example/views/index.jael @@ -0,0 +1,15 @@ + + + + + You said: {{ message }} + +
+ +
+ +
+
+
\ No newline at end of file diff --git a/packages/jael/angel_jael/example/views/layout.jael b/packages/jael/angel_jael/example/views/layout.jael new file mode 100644 index 00000000..0c091ae4 --- /dev/null +++ b/packages/jael/angel_jael/example/views/layout.jael @@ -0,0 +1,19 @@ + + + + + {{title}} + + +

+ {{title}} +

+ + Content goes here. + + + + \ No newline at end of file diff --git a/packages/jael/angel_jael/lib/angel_jael.dart b/packages/jael/angel_jael/lib/angel_jael.dart new file mode 100644 index 00000000..0c9946d4 --- /dev/null +++ b/packages/jael/angel_jael/lib/angel_jael.dart @@ -0,0 +1,71 @@ +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'; + +/// 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. +/// +/// To apply additional transforms to parsed documents, provide a set of [patch] functions. +AngelConfigurer jael(Directory viewsDirectory, + {String fileExtension, + bool strictResolution: false, + bool cacheViews: false, + Iterable patch, + bool asDSX: false, + CodeBuffer createBuffer()}) { + var cache = {}; + fileExtension ??= '.jael'; + createBuffer ??= () => new CodeBuffer(); + + return (Angel app) async { + app.viewGenerator = (String name, [Map locals]) async { + var errors = []; + 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, asDSX: asDSX == true, onError: errors.add); + processed = doc; + + try { + processed = await resolve(doc, viewsDirectory, + patch: patch, onError: errors.add); + } catch (_) { + // Ignore these errors, so that we can show syntax errors. + } + + if (cacheViews == true) { + cache[name] = processed; + } + } + + var buf = createBuffer(); + var scope = new SymbolTable( + values: locals?.keys?.fold>({}, + (out, k) => out..[k.toString()] = locals[k]) ?? + {}); + + if (errors.isEmpty) { + try { + const Renderer().render(processed, buf, scope, + strictResolution: strictResolution == true); + return buf.toString(); + } on JaelError catch (e) { + errors.add(e); + } + } + + Renderer.errorDocument(errors, buf..clear()); + return buf.toString(); + }; + }; +} diff --git a/packages/jael/angel_jael/mono_pkg.yaml b/packages/jael/angel_jael/mono_pkg.yaml new file mode 100644 index 00000000..e69de29b diff --git a/packages/jael/angel_jael/pubspec.yaml b/packages/jael/angel_jael/pubspec.yaml new file mode 100644 index 00000000..07f4b386 --- /dev/null +++ b/packages/jael/angel_jael/pubspec.yaml @@ -0,0 +1,19 @@ +name: angel_jael +version: 2.0.0 +description: Angel support for the Jael templating engine, similar to Blade or Liquid. +author: Tobe O +homepage: https://github.com/angel-dart/jael/tree/master/jael +environment: + sdk: ">=2.0.0-dev <=3.0.0" +dependencies: + angel_framework: ^2.0.0-alpha + code_buffer: ^1.0.0 + file: ^5.0.0 + jael: ^2.0.0 + jael_preprocessor: #^2.0.0 + path: ../jael_preprocessor + symbol_table: ^2.0.0 +dev_dependencies: + angel_test: ^2.0.0-alpha + html: + test: ^1.0.0 diff --git a/packages/jael/angel_jael/test/all_test.dart b/packages/jael/angel_jael/test/all_test.dart new file mode 100644 index 00000000..3ddaa039 --- /dev/null +++ b/packages/jael/angel_jael/test/all_test.dart @@ -0,0 +1,84 @@ +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_jael/angel_jael.dart'; +import 'package:angel_test/angel_test.dart'; +import 'package:file/memory.dart'; +import 'package:html/parser.dart' as html; +import 'package:logging/logging.dart'; +import 'package:test/test.dart'; + +main() { + // These tests need not actually test that the preprocessor or renderer works, + // because those packages are already tested. + // + // Instead, just test that we can render at all. + TestClient client; + + setUp(() async { + var app = new Angel(); + app.configuration['properties'] = app.configuration; + + var fileSystem = new MemoryFileSystem(); + var viewsDirectory = fileSystem.directory('views')..createSync(); + + viewsDirectory.childFile('layout.jael').writeAsStringSync(''' + + + + Hello + + + + Fallback content + + + + '''); + + viewsDirectory.childFile('github.jael').writeAsStringSync(''' + + {{username}} + + '''); + + app.get('/github/:username', (req, res) { + var username = req.params['username']; + return res.render('github', {'username': username}); + }); + + await app.configure( + jael(viewsDirectory), + ); + + app.fallback((req, res) => throw new AngelHttpException.notFound()); + + app.logger = new Logger('angel') + ..onRecord.listen((rec) { + print(rec); + if (rec.error != null) print(rec.error); + if (rec.stackTrace != null) print(rec.stackTrace); + }); + + client = await connectTo(app); + }); + + test('can render', () async { + var response = await client.get('/github/thosakwe'); + print('Body:\n${response.body}'); + expect( + html.parse(response.body).outerHtml, + html + .parse(''' + + + + Hello + + + + thosakwe + +''' + .trim()) + .outerHtml); + }); +} diff --git a/packages/jael/jael.iml b/packages/jael/jael.iml new file mode 100644 index 00000000..edffca2f --- /dev/null +++ b/packages/jael/jael.iml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/jael/jael/.gitignore b/packages/jael/jael/.gitignore new file mode 100644 index 00000000..cab9622e --- /dev/null +++ b/packages/jael/jael/.gitignore @@ -0,0 +1,16 @@ +# Created by .ignore support plugin (hsz.mobi) +### Dart template +# See https://www.dartlang.org/tools/private-files.html + +# Files and directories created by pub +.packages +.pub/ +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +.dart_tool \ No newline at end of file diff --git a/packages/jael/jael/CHANGELOG.md b/packages/jael/jael/CHANGELOG.md new file mode 100644 index 00000000..c40d909f --- /dev/null +++ b/packages/jael/jael/CHANGELOG.md @@ -0,0 +1,42 @@ +# 2.0.2 +* Fixed handling of `if` in non-strict mode. +* Roll `JaelFormatter` and `jaelfmt`. + +# 2.0.1 +* Fixed bug where the `textarea` name check would never return `true`. + +# 2.0.0+1 +* Meta-update for Pub score. + +# 2.0.0 +* Dart 2 updates. +* Remove usage of `package:dart2_constant`. + +# 1.0.6+1 +* Ensure `` passes attributes. + +# 1.0.6 +* Add `index-as` to `for-each`. +* Support registering + rendering custom elements. +* Improve handling of booleans in non-strict mode. + +# 1.0.5 +* Add support for DSX, a port of JSX to Dart. + +# 1.0.4 +* Skip HTML comments in free text. + +# 1.0.3 +* Fix a scanner bug that prevented proper parsing of HTML nodes +followed by free text. +* Don't trim `