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/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_builder.dart';
|
||||||
export 'src/dom_node.dart';
|
export 'src/dom_node.dart';
|
||||||
export 'src/fn.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);
|
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: ^1.0.0
|
||||||
build_config: ^0.3.0
|
build_config: ^0.3.0
|
||||||
code_builder: ^3.0.0
|
code_builder: ^3.0.0
|
||||||
|
jael: ^2.0.0
|
||||||
|
jael_preprocessor: ^2.0.0
|
||||||
source_gen: ^0.9.0
|
source_gen: ^0.9.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^1.0.0
|
build_runner: ^1.0.0
|
||||||
|
|
Loading…
Reference in a new issue