Last active
May 29, 2024 21:21
-
-
Save rodydavis/53d371e9e15147fe54dcf349bdc3452d to your computer and use it in GitHub Desktop.
Example of a possible Dart DSX (JSX like syntax) inspired by Templ in Go lang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:io'; | |
void main() { | |
final file = File('lib/hello.dsx'); | |
final out = File('lib/hello.g.dart'); | |
out.createSync(); | |
out.writeAsStringSync(convert(file.readAsStringSync())); | |
} | |
String convert(String raw) { | |
final result = StringBuffer(); | |
final lines = raw.split('\n'); | |
var isAsync = false; | |
for (var i = 0; i < lines.length; i++) { | |
var line = lines[i]; | |
if (line.trimLeft().startsWith('template ')) { | |
isAsync = false; | |
if (line.contains(') async {')) { | |
isAsync = true; | |
line = line.replaceFirst('template ', 'Stream<String> '); | |
line = line.replaceAll(') async {', ') async* {'); | |
} else { | |
line = line.replaceFirst('template ', 'Iterable<String> '); | |
line = line.replaceAll(') {', ') sync* {'); | |
} | |
result.writeln(line); | |
continue; | |
} else if (line.trimLeft().startsWith('<')) { | |
// Convert to string replace | |
result.write(" yield '"); | |
result.write(line.trimLeft()); | |
result.writeln("';"); | |
void addRawTag(String tag) { | |
if (line.trimLeft().startsWith('<$tag')) { | |
line = lines[++i]; | |
while (!line.trimLeft().startsWith('</$tag')) { | |
result.write(' yield "'); | |
result.write(line.replaceFirst(' ', '')); | |
result.writeln('";'); | |
line = lines[++i]; | |
} | |
result.write(" yield '"); | |
result.write(line.trimLeft()); | |
result.writeln("';"); | |
} | |
} | |
const tags = ['style', 'script']; | |
for (final tag in tags) { | |
addRawTag(tag); | |
} | |
continue; | |
} else if (line.trimLeft().startsWith('@')) { | |
// Convert to string replace | |
result.write(' yield* '); | |
if (isAsync) { | |
result.write(' Stream.fromIterable('); | |
} | |
result.write(line.replaceFirst(' ', '').replaceFirst('@', '')); | |
if (isAsync) { | |
result.write(' )'); | |
} | |
result.writeln(';'); | |
continue; | |
} | |
result.writeln(line); | |
} | |
return result.toString(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template Hello(String name, {bool active = false}) { | |
<div>Hello, ${name}!</div> | |
if (active) { | |
<div class="badge">You are awesome!</div> | |
} | |
} | |
template Base(String title) async { | |
<html> | |
<head> | |
<title>${title}</title> | |
<style> | |
body { | |
font-family: 'Roboto'; | |
} | |
</style> | |
</head> | |
<body> | |
@Hello('World', active: true) | |
</body> | |
</html> | |
} | |
template RemoteData(String path) async { | |
final response = await Future.value(0); | |
<div>Result: $response</div> | |
} | |
template Counter(int id, [int count = 0]) { | |
<h2>Counter: $id</h2> | |
<button id="counter-$id" data-count="$count">Count: $count</button> | |
<script> | |
const counter_$id = document.querySelector(`#counter-$id`); | |
counter_$id.addEventListener('click', inc, false); | |
function inc() { | |
let count = parseInt(counter_$id.getAttribute('data-count')); | |
count += 1; | |
counter_$id.innerHTML = `Count: \${count}`; | |
counter_$id.setAttribute('data-count', count); | |
} | |
</script> | |
} | |
template Counters(int count) { | |
<h1>Counters</h1> | |
for (var i = 0; i < count; i++) { | |
@Counter(i); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Iterable<String> Hello(String name, {bool active = false}) sync* { | |
yield '<div>Hello, ${name}!</div>'; | |
if (active) { | |
yield '<div class="badge">You are awesome!</div>'; | |
} | |
} | |
Stream<String> Base(String title) async* { | |
yield '<html>'; | |
yield '<head>'; | |
yield '<title>${title}</title>'; | |
yield '<style>'; | |
yield " body {"; | |
yield " font-family: 'Roboto';"; | |
yield " }"; | |
yield '</style>'; | |
yield '</head>'; | |
yield '<body>'; | |
yield* Stream.fromIterable( Hello('World', active: true) ); | |
yield '</body>'; | |
yield '</html>'; | |
} | |
Stream<String> RemoteData(String path) async* { | |
final response = await Future.value(0); | |
yield '<div>Result: $response</div>'; | |
} | |
Iterable<String> Counter(int id, [int count = 0]) sync* { | |
yield '<h2>Counter: $id</h2>'; | |
yield '<button id="counter-$id" data-count="$count">Count: $count</button>'; | |
yield '<script>'; | |
yield " const counter_$id = document.querySelector(`#counter-$id`);"; | |
yield " counter_$id.addEventListener('click', inc, false);"; | |
yield ""; | |
yield " function inc() {"; | |
yield "let count = parseInt(counter_$id.getAttribute('data-count'));"; | |
yield "count += 1;"; | |
yield "counter_$id.innerHTML = `Count: \${count}`;"; | |
yield "counter_$id.setAttribute('data-count', count);"; | |
yield " }"; | |
yield '</script>'; | |
} | |
Iterable<String> Counters(int count) sync* { | |
yield '<h1>Counters</h1>'; | |
for (var i = 0; i < count; i++) { | |
yield* Counter(i);; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment