diff --git a/third_party/packages/mustache_template/CHANGELOG.md b/third_party/packages/mustache_template/CHANGELOG.md index ed2daa26..2300e9ef 100644 --- a/third_party/packages/mustache_template/CHANGELOG.md +++ b/third_party/packages/mustache_template/CHANGELOG.md @@ -2,6 +2,7 @@ * Updates metadata for move to https://github.com/flutter/core-packages. * Updates minimum supported SDK version to Flutter 3.38/Dart 3.10. +* Adds example app demonstrating basic templates, nested paths, partials, and lambdas. ## 2.0.4 diff --git a/third_party/packages/mustache_template/README.md b/third_party/packages/mustache_template/README.md index cf4dab61..f6f3c13c 100644 --- a/third_party/packages/mustache_template/README.md +++ b/third_party/packages/mustache_template/README.md @@ -1,3 +1,5 @@ + + # Mustache templates A Dart library to parse and render [mustache templates](https://mustache.github.io/). @@ -7,29 +9,25 @@ See the [mustache manual](https://mustache.github.io/mustache.5.html) for detail This library passes all [mustache specification](https://github.com/mustache/spec/tree/master/specs) tests. ## Example usage + + ```dart -import 'package:mustache_template/mustache_template.dart'; - -main() { - var source = ''' - {{# names }} -
{{ lastname }}, {{ firstname }}
- {{/ names }} - {{^ names }} -
No names.
- {{/ names }} - {{! I am a comment. }} - '''; - - var template = Template(source, name: 'template-filename.html'); - - var output = template.renderString({'names': [ - {'firstname': 'Greg', 'lastname': 'Lowe'}, - {'firstname': 'Bob', 'lastname': 'Johnson'} - ]}); - - print(output); -} +final source = ''' +{{# names }} +
{{ lastname }}, {{ firstname }}
+{{/ names }} +{{^ names }} +
No names.
+{{/ names }} +{{! I am a comment. }} +'''; +final template = Template(source, name: 'template-filename.html'); +final output = template.renderString({ + 'names': [ + {'firstname': 'Greg', 'lastname': 'Lowe'}, + {'firstname': 'Bob', 'lastname': 'Johnson'}, + ], +}); ``` A template is parsed when it is created, after parsing it can be rendered any number of times with different values. A TemplateException is thrown if there is a problem parsing or rendering the template. @@ -53,65 +51,45 @@ By default all output from `{{variable}}` tags is html escaped, this behaviour c ## Nested paths + ```dart - var t = Template('{{ author.name }}'); - var output = template.renderString({'author': {'name': 'Greg Lowe'}}); +final template = Template('{{ author.name }}'); +final output = template.renderString({'author': {'name': 'Greg Lowe'}}); ``` ## Partials - example usage + ```dart - -var partial = Template('{{ foo }}', name: 'partial'); - -var resolver = (String name) { - if (name == 'partial-name') { // Name of partial tag. - return partial; - } +final partial = Template('{{ foo }}', name: 'partial'); +final resolver = (String name) { + if (name == 'partial-name') { + return partial; + } + return null; }; - -var t = Template('{{> partial-name }}', partialResolver: resolver); - -var output = t.renderString({'foo': 'bar'}); // bar - +final template = Template('{{> partial-name }}', partialResolver: resolver); +final output = template.renderString({'foo': 'bar'}); // bar ``` ## Lambdas - example usage + ```dart -var t = Template('{{# foo }}'); -var lambda = (_) => 'bar'; -t.renderString({'foo': lambda}); // bar -``` - -```dart -var t = Template('{{# foo }}hidden{{/ foo }}'); -var lambda = (_) => 'shown'; -t.renderString('foo': lambda); // shown -``` - -```dart -var t = Template('{{# foo }}oi{{/ foo }}'); -var lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; -t.renderString({'foo': lambda}); // OI -``` - -```dart -var t = Template('{{# foo }}{{bar}}{{/ foo }}'); -var lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; -t.renderString({'foo': lambda, 'bar': 'pub'}); // PUB -``` - -```dart -var t = Template('{{# foo }}{{bar}}{{/ foo }}'); -var lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; -t.renderString({'foo': lambda, 'bar': 'pub'}); // PUB +final template = Template('{{# foo }}{{bar}}{{/ foo }}'); +final lambda = + (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; +final output = + template.renderString({'foo': lambda, 'bar': 'pub'}); // PUB ``` In the following example `LambdaContext.renderSource(source)` re-parses the source string in the current context, this is the default behaviour in many mustache implementations. Since re-parsing the content is slow, and often not required, this library makes this step optional. + ```dart -var t = Template('{{# foo }}{{bar}}{{/ foo }}'); -var lambda = (LambdaContext ctx) => ctx.renderSource(ctx.source + ' {{cmd}}'); -t.renderString({'foo': lambda, 'bar': 'pub', 'cmd': 'build'}); // pub build -``` +final template = Template('{{# foo }}{{bar}}{{/ foo }}'); +final lambda = + (LambdaContext ctx) => ctx.renderSource(ctx.source + ' {{cmd}}'); +final output = template + .renderString({'foo': lambda, 'bar': 'pub', 'cmd': 'build'}); // pub build +``` \ No newline at end of file diff --git a/third_party/packages/mustache_template/example/lib/readme_excerpts.dart b/third_party/packages/mustache_template/example/lib/readme_excerpts.dart new file mode 100644 index 00000000..2e0ba5a1 --- /dev/null +++ b/third_party/packages/mustache_template/example/lib/readme_excerpts.dart @@ -0,0 +1,76 @@ +// ignore_for_file: avoid_print + +import 'package:mustache_template/mustache_template.dart'; + +void renderBasicTemplate() { + // #docregion basic + final source = ''' +{{# names }} +
{{ lastname }}, {{ firstname }}
+{{/ names }} +{{^ names }} +
No names.
+{{/ names }} +{{! I am a comment. }} +'''; + final template = Template(source, name: 'template-filename.html'); + final output = template.renderString({ + 'names': [ + {'firstname': 'Greg', 'lastname': 'Lowe'}, + {'firstname': 'Bob', 'lastname': 'Johnson'}, + ], + }); + // #enddocregion basic + print(output); +} + +void renderNestedPaths() { + // #docregion nested + final template = Template('{{ author.name }}'); + final output = template.renderString({ + 'author': {'name': 'Greg Lowe'}, + }); + // #enddocregion nested + print(output); +} + +void renderPartials() { + // #docregion partials + final partial = Template('{{ foo }}', name: 'partial'); + final resolver = (String name) { + if (name == 'partial-name') { + return partial; + } + return null; + }; + final template = Template('{{> partial-name }}', partialResolver: resolver); + final output = template.renderString({'foo': 'bar'}); // bar + // #enddocregion partials + print(output); +} + +void renderLambdaRenderString() { + // #docregion lambda-render-string + final template = Template('{{# foo }}{{bar}}{{/ foo }}'); + final lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; + final output = template.renderString({'foo': lambda, 'bar': 'pub'}); // PUB + // #enddocregion lambda-render-string + print(output); +} + +void renderLambdaRenderSource() { + // #docregion lambda-render-source + final template = Template('{{# foo }}{{bar}}{{/ foo }}'); + final lambda = (LambdaContext ctx) => ctx.renderSource(ctx.source + ' {{cmd}}'); + final output = template.renderString({'foo': lambda, 'bar': 'pub', 'cmd': 'build'}); // pub build + // #enddocregion lambda-render-source + print(output); +} + +void main() { + renderBasicTemplate(); + renderNestedPaths(); + renderPartials(); + renderLambdaRenderString(); + renderLambdaRenderSource(); +} diff --git a/third_party/packages/mustache_template/example/pubspec.yaml b/third_party/packages/mustache_template/example/pubspec.yaml new file mode 100644 index 00000000..4a95d972 --- /dev/null +++ b/third_party/packages/mustache_template/example/pubspec.yaml @@ -0,0 +1,11 @@ +name: mustache_template_examples +description: Example code for mustache_template usage +version: 0.0.1 +publish_to: none + +environment: + sdk: ^3.10.0 + +dependencies: + mustache_template: + path: ../ \ No newline at end of file diff --git a/third_party/packages/mustache_template/test/example_test.dart b/third_party/packages/mustache_template/test/example_test.dart new file mode 100644 index 00000000..05502f14 --- /dev/null +++ b/third_party/packages/mustache_template/test/example_test.dart @@ -0,0 +1,59 @@ +import 'package:mustache_template/mustache_template.dart'; +import 'package:test/test.dart'; + +void main() { + test('renders basic list template', () { + final source = ''' +{{# names }} +
{{ lastname }}, {{ firstname }}
+{{/ names }} +{{^ names }} +
No names.
+{{/ names }} +'''; + final template = Template(source, name: 'template-filename.html'); + final output = template.renderString({ + 'names': [ + {'firstname': 'Greg', 'lastname': 'Lowe'}, + {'firstname': 'Bob', 'lastname': 'Johnson'}, + ], + }); + expect(output, contains('Lowe, Greg')); + expect(output, contains('Johnson, Bob')); + }); + + test('renders nested paths', () { + final template = Template('{{ author.name }}'); + final output = template.renderString({ + 'author': {'name': 'Greg Lowe'}, + }); + expect(output, equals('Greg Lowe')); + }); + + test('renders partials', () { + final partial = Template('{{ foo }}', name: 'partial'); + final resolver = (String name) { + if (name == 'partial-name') { + return partial; + } + return null; + }; + final template = Template('{{> partial-name }}', partialResolver: resolver); + final output = template.renderString({'foo': 'bar'}); + expect(output, equals('bar')); + }); + + test('renders lambda using renderString', () { + final template = Template('{{# foo }}{{bar}}{{/ foo }}'); + final lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; + final output = template.renderString({'foo': lambda, 'bar': 'pub'}); + expect(output, equals('PUB')); + }); + + test('renders lambda using renderSource', () { + final template = Template('{{# foo }}{{bar}}{{/ foo }}'); + final lambda = (LambdaContext ctx) => ctx.renderSource(ctx.source + ' {{cmd}}'); + final output = template.renderString({'foo': lambda, 'bar': 'pub', 'cmd': 'build'}); + expect(output, equals('pub build')); + }); +}