Examples + basic builder
This commit is contained in:
parent
4cbfd3c251
commit
f34f28bb7b
14 changed files with 2706 additions and 1 deletions
10
jael_web/build.yaml
Normal file
10
jael_web/build.yaml
Normal file
|
@ -0,0 +1,10 @@
|
|||
builders:
|
||||
jael_web:
|
||||
import: "package:jael_web/builder.dart"
|
||||
builder_factories:
|
||||
- jaelComponentBuilder
|
||||
build_extensions:
|
||||
.dart:
|
||||
- .jael_web_cmp.g.part
|
||||
auto_apply: root_package
|
||||
applies_builders: ["source_gen|combining_builder", "source_gen|part_cleanup"]
|
|
@ -1,3 +1,30 @@
|
|||
import 'package:jael_web/jael_web.dart';
|
||||
import 'package:jael_web/elements.dart';
|
||||
part 'main.g.dart';
|
||||
|
||||
void main() {}
|
||||
@Dsx(template: '''
|
||||
<div>
|
||||
<h1>Hello, Jael!</h1>
|
||||
<i>Current time: {now}</i>
|
||||
</div>
|
||||
''')
|
||||
class Hello extends Component with _HelloJaelTemplate {
|
||||
DateTime get now => DateTime.now();
|
||||
}
|
||||
|
||||
// Could also have been:
|
||||
class Hello2 extends Component {
|
||||
DateTime get now => DateTime.now();
|
||||
|
||||
@override
|
||||
DomNode render() {
|
||||
return div(c: [
|
||||
h1(c: [
|
||||
text('Hello, Jael!'),
|
||||
]),
|
||||
i(c: [
|
||||
text('Current time: $now'),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
18
jael_web/example/main.g.dart
Normal file
18
jael_web/example/main.g.dart
Normal file
|
@ -0,0 +1,18 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'main.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JaelComponentGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _HelloJaelTemplate implements Component<dynamic> {
|
||||
DateTime get now;
|
||||
@override
|
||||
DomNode render() {
|
||||
return h('div', {}, [
|
||||
h('h1', {}, [text('Hello, Jael!')]),
|
||||
h('i', {}, [text('Current time: '), text(now.toString())])
|
||||
]);
|
||||
}
|
||||
}
|
32
jael_web/example/stateful.dart
Normal file
32
jael_web/example/stateful.dart
Normal file
|
@ -0,0 +1,32 @@
|
|||
import 'dart:async';
|
||||
import 'package:jael_web/jael_web.dart';
|
||||
part 'stateful.g.dart';
|
||||
|
||||
void main() {}
|
||||
|
||||
class _AppState {
|
||||
final int ticks;
|
||||
|
||||
_AppState({this.ticks});
|
||||
|
||||
_AppState copyWith({int ticks}) {
|
||||
return _AppState(ticks: ticks ?? this.ticks);
|
||||
}
|
||||
}
|
||||
|
||||
@Dsx(template: '<div>Tick count: {state.ticks}</div>')
|
||||
class StatefulApp extends Component<_AppState> with _StatefulAppJaelTemplate {
|
||||
Timer _timer;
|
||||
|
||||
StatefulApp() {
|
||||
state =_AppState(ticks: 0);
|
||||
_timer = Timer.periodic(Duration(seconds: 1), (t) {
|
||||
setState(state.copyWith(ticks: t.tick));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void beforeDestroy() {
|
||||
_timer.cancel();
|
||||
}
|
||||
}
|
15
jael_web/example/stateful.g.dart
Normal file
15
jael_web/example/stateful.g.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'stateful.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JaelComponentGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _StatefulAppJaelTemplate implements Component<_AppState> {
|
||||
Timer get _timer;
|
||||
@override
|
||||
DomNode render() {
|
||||
return h('div', {}, [text('Tick count: '), text(state.ticks.toString())]);
|
||||
}
|
||||
}
|
1
jael_web/lib/builder.dart
Normal file
1
jael_web/lib/builder.dart
Normal file
|
@ -0,0 +1 @@
|
|||
export 'src/builder/builder.dart';
|
1
jael_web/lib/elements.dart
Normal file
1
jael_web/lib/elements.dart
Normal file
|
@ -0,0 +1 @@
|
|||
export 'src/elements.dart';
|
|
@ -3,3 +3,4 @@ export 'src/component.dart';
|
|||
export 'src/dom_builder.dart';
|
||||
export 'src/dom_node.dart';
|
||||
export 'src/fn.dart';
|
||||
export 'src/jael_component.dart';
|
||||
|
|
123
jael_web/lib/src/builder/builder.dart
Normal file
123
jael_web/lib/src/builder/builder.dart
Normal file
|
@ -0,0 +1,123 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:code_builder/code_builder.dart';
|
||||
import 'package:jael/jael.dart' as jael;
|
||||
import 'package:jael_preprocessor/jael_preprocessor.dart' as jael;
|
||||
import 'package:jael_web/jael_web.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
import 'util.dart';
|
||||
|
||||
Builder jaelComponentBuilder(_) {
|
||||
return SharedPartBuilder([JaelComponentGenerator()], 'jael_web_cmp');
|
||||
}
|
||||
|
||||
class JaelComponentGenerator extends GeneratorForAnnotation<Jael> {
|
||||
@override
|
||||
Future<String> generateForAnnotatedElement(
|
||||
Element element, ConstantReader annotation, BuildStep buildStep) async {
|
||||
if (element is ClassElement) {
|
||||
// Load the template
|
||||
String templateString;
|
||||
var inputId = buildStep.inputId;
|
||||
var ann = Jael(
|
||||
template: annotation.peek('template')?.stringValue,
|
||||
templateUrl: annotation.peek('templateUrl')?.stringValue,
|
||||
asDsx: annotation.peek('asDsx')?.boolValue ?? false,
|
||||
);
|
||||
|
||||
if (ann.template == null && ann.templateUrl == null) {
|
||||
throw 'Both `template` and `templateUrl` cannot be null.';
|
||||
}
|
||||
|
||||
if (ann.template != null)
|
||||
templateString = ann.template;
|
||||
else {
|
||||
var dir = p.dirname(inputId.path);
|
||||
var assetId = AssetId(inputId.package, p.join(dir, ann.templateUrl));
|
||||
if (!await buildStep.canRead(assetId)) {
|
||||
throw 'Cannot find template "${assetId.uri}"';
|
||||
} else {
|
||||
templateString = await buildStep.readAsString(assetId);
|
||||
}
|
||||
}
|
||||
|
||||
var fs = BuildFileSystem(buildStep, inputId.package);
|
||||
var errors = <jael.JaelError>[];
|
||||
var doc = await jael.parseDocument(templateString,
|
||||
sourceUrl: inputId.uri, asDSX: ann.asDsx, onError: errors.add);
|
||||
if (errors.isEmpty) {
|
||||
doc = await jael.resolve(doc, fs.file(inputId.uri).parent,
|
||||
onError: errors.add);
|
||||
}
|
||||
|
||||
if (errors.isNotEmpty) {
|
||||
errors.forEach(log.severe);
|
||||
throw 'Jael processing finished with ${errors.length} error(s).';
|
||||
}
|
||||
|
||||
// Generate a _XJaelTemplate mixin class
|
||||
var clazz = Class((b) {
|
||||
b
|
||||
..abstract = true
|
||||
..name = '_${element.name}JaelTemplate'
|
||||
..implements.add(convertTypeReference(element.supertype));
|
||||
|
||||
// Add fields corresponding to each of the class's fields.
|
||||
for (var field in element.fields) {
|
||||
b.methods.add(Method((b) {
|
||||
b
|
||||
..name = field.name
|
||||
..type = MethodType.getter
|
||||
..returns = convertTypeReference(field.type);
|
||||
}));
|
||||
}
|
||||
|
||||
// Add a render() stub
|
||||
b.methods.add(Method((b) {
|
||||
b
|
||||
..name = 'render'
|
||||
..returns = refer('DomNode')
|
||||
..annotations.add(refer('override'))
|
||||
..body = Block((b) {
|
||||
var result = compileElementChild(doc.root);
|
||||
b.addExpression(result.returned);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
return clazz.accept(DartEmitter()).toString();
|
||||
} else {
|
||||
throw '@Jael() is only supported for classes.';
|
||||
}
|
||||
}
|
||||
|
||||
Expression compileElementChild(jael.ElementChild child) {
|
||||
if (child is jael.TextNode || child is jael.Text) {
|
||||
return refer('text').call([literalString(child.span.text)]);
|
||||
} else if (child is jael.Interpolation) {
|
||||
Expression expr = CodeExpression(Code(child.expression.span.text));
|
||||
expr = expr.property('toString').call([]);
|
||||
return refer('text').call([expr]);
|
||||
} else if (child is jael.Element) {
|
||||
// TODO: Handle strict resolution
|
||||
var attrs = <String, Expression>{};
|
||||
for (var attr in child.attributes) {
|
||||
attrs[attr.name] = attr.value == null
|
||||
? literalTrue
|
||||
: CodeExpression(Code(attr.value.span.text));
|
||||
}
|
||||
|
||||
return refer('h').call([
|
||||
literalString(child.tagName.name),
|
||||
literalMap(attrs),
|
||||
literalList(child.children.map(compileElementChild)),
|
||||
]);
|
||||
// return refer(child.tagName.name).newInstance([]);
|
||||
} else {
|
||||
throw 'Unsupported: $child';
|
||||
}
|
||||
}
|
||||
}
|
375
jael_web/lib/src/builder/util.dart
Normal file
375
jael_web/lib/src/builder/util.dart
Normal file
|
@ -0,0 +1,375 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:code_builder/code_builder.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:path/src/context.dart';
|
||||
|
||||
/// Converts a [DartType] to a [TypeReference].
|
||||
TypeReference convertTypeReference(DartType t) {
|
||||
return new TypeReference((b) {
|
||||
b..symbol = t.name;
|
||||
|
||||
if (t is InterfaceType) {
|
||||
b.types.addAll(t.typeArguments.map(convertTypeReference));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
UnsupportedError _unsupported() =>
|
||||
UnsupportedError('Not support in R/O build file system.');
|
||||
|
||||
class BuildFileSystem extends FileSystem {
|
||||
final AssetReader reader;
|
||||
final String package;
|
||||
Context _path = Context();
|
||||
|
||||
BuildFileSystem(this.reader, this.package);
|
||||
|
||||
Context get path => _path;
|
||||
|
||||
@override
|
||||
Directory get currentDirectory {
|
||||
return BuildSystemDirectory(this, reader, package, _path.current);
|
||||
}
|
||||
|
||||
set currentDirectory(value) {
|
||||
if (value is Directory) {
|
||||
_path = Context(current: value.path);
|
||||
} else if (value is String) {
|
||||
_path = Context(current: value);
|
||||
} else {
|
||||
throw ArgumentError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Directory directory(path) {
|
||||
String p;
|
||||
if (path is String)
|
||||
p = path;
|
||||
else if (path is Uri)
|
||||
p = p.toString();
|
||||
else if (path is FileSystemEntity)
|
||||
p = path.path;
|
||||
else
|
||||
throw ArgumentError();
|
||||
return BuildSystemDirectory(this, reader, package, p);
|
||||
}
|
||||
|
||||
@override
|
||||
File file(path) {
|
||||
String p;
|
||||
if (path is String)
|
||||
p = path;
|
||||
else if (path is Uri)
|
||||
p = p.toString();
|
||||
else if (path is FileSystemEntity)
|
||||
p = path.path;
|
||||
else
|
||||
throw ArgumentError();
|
||||
return BuildSystemFile(this, reader, package, p);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> identical(String path1, String path2) => throw _unsupported();
|
||||
|
||||
@override
|
||||
bool identicalSync(String path1, String path2) => throw _unsupported();
|
||||
|
||||
@override
|
||||
bool get isWatchSupported => false;
|
||||
|
||||
@override
|
||||
Link link(path) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<FileStat> stat(String path) => throw _unsupported();
|
||||
|
||||
@override
|
||||
FileStat statSync(String path) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Directory get systemTempDirectory => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<FileSystemEntityType> type(String path, {bool followLinks = true}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
FileSystemEntityType typeSync(String path, {bool followLinks = true}) =>
|
||||
throw _unsupported();
|
||||
}
|
||||
|
||||
class BuildSystemFile extends File {
|
||||
final BuildFileSystem fileSystem;
|
||||
final AssetReader reader;
|
||||
final String package;
|
||||
final String path;
|
||||
|
||||
BuildSystemFile(this.fileSystem, this.reader, this.package, this.path);
|
||||
|
||||
Uri get uri => fileSystem.path.toUri(path);
|
||||
|
||||
@override
|
||||
File get absolute => this;
|
||||
|
||||
@override
|
||||
String get basename => fileSystem.path.basename(path);
|
||||
|
||||
@override
|
||||
Future<File> copy(String newPath) => throw _unsupported();
|
||||
|
||||
@override
|
||||
File copySync(String newPath) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<File> create({bool recursive = false}) => throw _unsupported();
|
||||
|
||||
@override
|
||||
void createSync({bool recursive = false}) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<FileSystemEntity> delete({bool recursive = false}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
void deleteSync({bool recursive = false}) => throw _unsupported();
|
||||
|
||||
@override
|
||||
String get dirname => fileSystem.path.dirname(path);
|
||||
|
||||
@override
|
||||
Future<bool> exists() => throw _unsupported();
|
||||
@override
|
||||
bool existsSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
bool get isAbsolute => true;
|
||||
|
||||
@override
|
||||
Future<DateTime> lastAccessed() => throw _unsupported();
|
||||
|
||||
@override
|
||||
DateTime lastAccessedSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<DateTime> lastModified() => throw _unsupported();
|
||||
|
||||
@override
|
||||
DateTime lastModifiedSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<int> length() => throw _unsupported();
|
||||
@override
|
||||
int lengthSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<RandomAccessFile> open({FileMode mode = FileMode.read}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
Stream<List<int>> openRead([int start, int end]) => throw _unsupported();
|
||||
|
||||
@override
|
||||
RandomAccessFile openSync({FileMode mode = FileMode.read}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
IOSink openWrite(
|
||||
{FileMode mode = FileMode.write, Encoding encoding = utf8}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
Directory get parent =>
|
||||
BuildSystemDirectory(fileSystem, reader, package, fileSystem.path.dirname(path));
|
||||
|
||||
@override
|
||||
Future<List<int>> readAsBytes() {
|
||||
var assetId = AssetId(package, path);
|
||||
return reader.readAsBytes(assetId);
|
||||
}
|
||||
|
||||
@override
|
||||
List<int> readAsBytesSync() => throw _unsupported();
|
||||
@override
|
||||
Future<List<String>> readAsLines({Encoding encoding = utf8}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
List<String> readAsLinesSync({Encoding encoding = utf8}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<String> readAsString({Encoding encoding = utf8}) {
|
||||
var assetId = AssetId(package, path);
|
||||
return reader.readAsString(assetId);
|
||||
}
|
||||
|
||||
@override
|
||||
String readAsStringSync({Encoding encoding = utf8}) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<File> rename(String newPath) => throw _unsupported();
|
||||
|
||||
@override
|
||||
File renameSync(String newPath) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<String> resolveSymbolicLinks() => throw _unsupported();
|
||||
|
||||
@override
|
||||
String resolveSymbolicLinksSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future setLastAccessed(DateTime time) => throw _unsupported();
|
||||
|
||||
@override
|
||||
void setLastAccessedSync(DateTime time) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future setLastModified(DateTime time) => throw _unsupported();
|
||||
|
||||
@override
|
||||
void setLastModifiedSync(DateTime time) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<FileStat> stat() => throw _unsupported();
|
||||
|
||||
@override
|
||||
FileStat statSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
Stream<FileSystemEvent> watch(
|
||||
{int events = FileSystemEvent.all, bool recursive = false}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<File> writeAsBytes(List<int> bytes,
|
||||
{FileMode mode = FileMode.write, bool flush = false}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
void writeAsBytesSync(List<int> bytes,
|
||||
{FileMode mode = FileMode.write, bool flush = false}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<File> writeAsString(String contents,
|
||||
{FileMode mode = FileMode.write,
|
||||
Encoding encoding = utf8,
|
||||
bool flush = false}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
void writeAsStringSync(String contents,
|
||||
{FileMode mode = FileMode.write,
|
||||
Encoding encoding = utf8,
|
||||
bool flush = false}) =>
|
||||
throw _unsupported();
|
||||
}
|
||||
|
||||
class BuildSystemDirectory extends Directory {
|
||||
final BuildFileSystem fileSystem;
|
||||
final AssetReader reader;
|
||||
final String package;
|
||||
final String path;
|
||||
|
||||
BuildSystemDirectory(this.fileSystem, this.reader, this.package, this.path);
|
||||
|
||||
@override
|
||||
Directory get absolute => this;
|
||||
|
||||
@override
|
||||
String get basename => fileSystem.path.basename(path);
|
||||
|
||||
@override
|
||||
Directory childDirectory(String basename) {
|
||||
return BuildSystemDirectory(
|
||||
fileSystem, reader, package, fileSystem.path.join(path, basename));
|
||||
}
|
||||
|
||||
@override
|
||||
File childFile(String basename) {
|
||||
return BuildSystemFile(
|
||||
fileSystem, reader, package, fileSystem.path.join(path, basename));
|
||||
}
|
||||
|
||||
@override
|
||||
Link childLink(String basename) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<Directory> create({bool recursive = false}) => throw _unsupported();
|
||||
|
||||
@override
|
||||
void createSync({bool recursive = false}) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<Directory> createTemp([String prefix]) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Directory createTempSync([String prefix]) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<FileSystemEntity> delete({bool recursive = false}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
void deleteSync({bool recursive = false}) => throw _unsupported();
|
||||
|
||||
@override
|
||||
String get dirname => fileSystem.path.dirname(path);
|
||||
|
||||
@override
|
||||
Future<bool> exists() => throw _unsupported();
|
||||
|
||||
@override
|
||||
bool existsSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
bool get isAbsolute => true;
|
||||
|
||||
@override
|
||||
Stream<FileSystemEntity> list(
|
||||
{bool recursive = false, bool followLinks = true}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
List<FileSystemEntity> listSync(
|
||||
{bool recursive = false, bool followLinks = true}) =>
|
||||
throw _unsupported();
|
||||
|
||||
@override
|
||||
Directory get parent {
|
||||
return BuildSystemDirectory(
|
||||
fileSystem, reader, package, fileSystem.path.dirname(path));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Directory> rename(String newPath) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Directory renameSync(String newPath) => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<String> resolveSymbolicLinks() => throw _unsupported();
|
||||
|
||||
@override
|
||||
String resolveSymbolicLinksSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
Future<FileStat> stat() => throw _unsupported();
|
||||
|
||||
@override
|
||||
FileStat statSync() => throw _unsupported();
|
||||
|
||||
@override
|
||||
Uri get uri => fileSystem.path.toUri(path);
|
||||
|
||||
@override
|
||||
Stream<FileSystemEvent> watch(
|
||||
{int events = FileSystemEvent.all, bool recursive = false}) =>
|
||||
throw _unsupported();
|
||||
}
|
|
@ -6,3 +6,48 @@ abstract class BuilderNode extends DomNode {
|
|||
|
||||
void destroy<T>(DomBuilderElement<T> el);
|
||||
}
|
||||
|
||||
DomNode h(String tagName,
|
||||
[Map<String, dynamic> props = const {},
|
||||
Iterable<DomNode> children = const []]) {
|
||||
return _H(tagName, props, children);
|
||||
}
|
||||
|
||||
DomNode text(String value) => _Text(value);
|
||||
|
||||
class _Text extends BuilderNode {
|
||||
final String text;
|
||||
|
||||
_Text(this.text);
|
||||
|
||||
@override
|
||||
DomBuilderElement<T> build<T>(DomBuilder<T> dom) {
|
||||
dom.text(text);
|
||||
// TODO: implement build
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void destroy<T>(DomBuilderElement<T> el) {
|
||||
// TODO: implement destroy
|
||||
}
|
||||
}
|
||||
|
||||
class _H extends BuilderNode {
|
||||
final String tagName;
|
||||
final Map<String, dynamic> props;
|
||||
final Iterable<DomNode> children;
|
||||
|
||||
_H(this.tagName, this.props, this.children);
|
||||
|
||||
@override
|
||||
DomBuilderElement<T> build<T>(DomBuilder<T> dom) {
|
||||
// TODO: implement build
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void destroy<T>(DomBuilderElement<T> el) {
|
||||
// TODO: implement destroy
|
||||
}
|
||||
}
|
||||
|
|
2036
jael_web/lib/src/elements.dart
Normal file
2036
jael_web/lib/src/elements.dart
Normal file
File diff suppressed because it is too large
Load diff
19
jael_web/lib/src/jael_component.dart
Normal file
19
jael_web/lib/src/jael_component.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
/// A annotation for components that source-gen their `render()` methods.
|
||||
class Jael {
|
||||
/// The raw template.
|
||||
final String template;
|
||||
|
||||
/// The path to a [template].
|
||||
final String templateUrl;
|
||||
|
||||
/// Whether to parse the [template] as `DSX`.
|
||||
final bool asDsx;
|
||||
|
||||
const Jael({this.template, this.templateUrl, this.asDsx});
|
||||
}
|
||||
|
||||
/// Shorthand for enabling `DSX` syntax when using a [Jael] annotation.
|
||||
class Dsx extends Jael {
|
||||
const Dsx({String template, String templateUrl})
|
||||
: super(template: template, templateUrl: templateUrl, asDsx: true);
|
||||
}
|
|
@ -7,6 +7,8 @@ dependencies:
|
|||
build: ^1.0.0
|
||||
build_config: ^0.3.0
|
||||
code_builder: ^3.0.0
|
||||
jael: ^2.0.0
|
||||
jael_preprocessor: ^2.0.0
|
||||
source_gen: ^0.9.0
|
||||
dev_dependencies:
|
||||
build_runner: ^1.0.0
|
||||
|
|
Loading…
Reference in a new issue