Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion script/configs/temp_exclude_excerpt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
# https://github.com/flutter/flutter/issues/102679
- espresso
- in_app_purchase/in_app_purchase
- mustache_template
- pointer_interceptor
- quick_actions/quick_actions
4 changes: 4 additions & 0 deletions third_party/packages/mustache_template/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.0.4

* Adds a runnable example app and refreshes README code samples.

## 2.0.3

* Updates minimum supported SDK version to Flutter 3.35/Dart 3.9.
Expand Down
121 changes: 69 additions & 52 deletions third_party/packages/mustache_template/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<?code-excerpt path-base="example/lib"?>

# Mustache templates

A Dart library to parse and render [mustache templates](https://mustache.github.io/).
Expand All @@ -7,29 +9,34 @@ See the [mustache manual](http://mustache.github.com/mustache.5.html) for detail
This library passes all [mustache specification](https://github.com/mustache/spec/tree/master/specs) tests.

## Example usage

<?code-excerpt "main.dart (ExampleUsage)" plaster="none"?>
```dart
import 'package:mustache_template/mustache_template.dart';

main() {
var source = '''
{{# names }}
<div>{{ lastname }}, {{ firstname }}</div>
{{/ names }}
{{^ names }}
<div>No names.</div>
{{/ 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);
void main() {
const source = '''
{{# names }}
<div>{{ lastname }}, {{ firstname }}</div>
{{/ names }}
{{^ names }}
<div>No names.</div>
{{/ names }}
{{! I am a comment. }}
''';

final template = Template(source, name: 'template-filename.html');

final String output = template.renderString({
'names': [
{'firstname': 'Greg', 'lastname': 'Lowe'},
{'firstname': 'Bob', 'lastname': 'Johnson'},
],
});

print(output);
}

```

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.
Expand All @@ -53,65 +60,75 @@ By default all output from `{{variable}}` tags is html escaped, this behaviour c

## Nested paths

<?code-excerpt "readme_excerpts.dart (NestedPaths)"?>
```dart
var t = Template('{{ author.name }}');
var output = template.renderString({'author': {'name': 'Greg Lowe'}});
final t = Template('{{ author.name }}');
final output = t.renderString({
'author': {'name': 'Greg Lowe'},
});
```

## Partials - example usage

<?code-excerpt "readme_excerpts.dart (Partials)"?>
```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') {
// Name of partial tag.
return partial;
}
return null;
};

var t = Template('{{> partial-name }}', partialResolver: resolver);

var output = t.renderString({'foo': 'bar'}); // bar
final t = Template('{{> partial-name }}', partialResolver: resolver);

final output = t.renderString({'foo': 'bar'}); // bar
```

## Lambdas - example usage

<?code-excerpt "readme_excerpts.dart (LambdaSimple)"?>
```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
final t = Template('{{# foo }}{{/ foo }}');
final lambda = (_) => 'bar';
final output = t.renderString({'foo': lambda}); // bar
```

<?code-excerpt "readme_excerpts.dart (LambdaShown)"?>
```dart
var t = Template('{{# foo }}oi{{/ foo }}');
var lambda = (LambdaContext ctx) => '<b>${ctx.renderString().toUpperCase()}</b>';
t.renderString({'foo': lambda}); // <b>OI</b>
final t = Template('{{# foo }}hidden{{/ foo }}');
final lambda = (_) => 'shown';
final output = t.renderString({'foo': lambda}); // shown
```

<?code-excerpt "readme_excerpts.dart (LambdaRender)"?>
```dart
var t = Template('{{# foo }}{{bar}}{{/ foo }}');
var lambda = (LambdaContext ctx) => '<b>${ctx.renderString().toUpperCase()}</b>';
t.renderString({'foo': lambda, 'bar': 'pub'}); // <b>PUB</b>
final t = Template('{{# foo }}oi{{/ foo }}');
final lambda = (LambdaContext ctx) =>
'<b>${ctx.renderString().toUpperCase()}</b>';
final output = t.renderString({'foo': lambda}); // <b>OI</b>
```

<?code-excerpt "readme_excerpts.dart (LambdaRenderBar)"?>
```dart
var t = Template('{{# foo }}{{bar}}{{/ foo }}');
var lambda = (LambdaContext ctx) => '<b>${ctx.renderString().toUpperCase()}</b>';
t.renderString({'foo': lambda, 'bar': 'pub'}); // <b>PUB</b>
final t = Template('{{# foo }}{{bar}}{{/ foo }}');
final lambda = (LambdaContext ctx) =>
'<b>${ctx.renderString().toUpperCase()}</b>';
final output = t.renderString({'foo': lambda, 'bar': 'pub'}); // <b>PUB</b>
```

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.

<?code-excerpt "readme_excerpts.dart (LambdaRenderSource)"?>
```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 t = Template('{{# foo }}{{bar}}{{/ foo }}');
final lambda = (LambdaContext ctx) =>
ctx.renderSource('${ctx.source} {{cmd}}');
final output = t.renderString({
'foo': lambda,
'bar': 'pub',
'cmd': 'build',
}); // pub build
```
56 changes: 56 additions & 0 deletions third_party/packages/mustache_template/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: avoid_print, prefer_function_declarations_over_variables

// #docregion ExampleUsage
import 'package:mustache_template/mustache_template.dart';

void main() {
// #enddocregion ExampleUsage
print('=== Basic Template ===');

// Basic template rendering with sections and inverted sections.
// #docregion ExampleUsage
const source = '''
{{# names }}
<div>{{ lastname }}, {{ firstname }}</div>
{{/ names }}
{{^ names }}
<div>No names.</div>
{{/ names }}
{{! I am a comment. }}
''';

final template = Template(source, name: 'template-filename.html');

final String output = template.renderString({
'names': [
{'firstname': 'Greg', 'lastname': 'Lowe'},
{'firstname': 'Bob', 'lastname': 'Johnson'},
],
});

print(output);
// #enddocregion ExampleUsage

// Nested paths
final nested = Template('{{ author.name }}');
print('=== Nested Paths ===');
print(
nested.renderString({
'author': {'name': 'Greg Lowe'},
}),
);

// Lambdas
final lambdaTemplate = Template('{{# transform }}hello{{/ transform }}');
final String Function(LambdaContext) lambda = (LambdaContext ctx) =>
ctx.renderString().toUpperCase();
print('=== Lambdas ===');
print(lambdaTemplate.renderString({'transform': lambda}));
// #docregion ExampleUsage
}

// #enddocregion ExampleUsage
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file exists solely to host compiled excerpts for README.md, and is not
// intended for use as an actual example application.

// ignore_for_file: avoid_print, public_member_api_docs, unreachable_from_main
// ignore_for_file: prefer_function_declarations_over_variables
// ignore_for_file: specify_nonobvious_local_variable_types

import 'package:mustache_template/mustache_template.dart';

String nestedPathsExample() {
// #docregion NestedPaths
final t = Template('{{ author.name }}');
final output = t.renderString({
'author': {'name': 'Greg Lowe'},
});
// #enddocregion NestedPaths
return output;
}

String partialsExample() {
// #docregion Partials
final partial = Template('{{ foo }}', name: 'partial');

final resolver = (String name) {
if (name == 'partial-name') {
// Name of partial tag.
return partial;
}
return null;
};

final t = Template('{{> partial-name }}', partialResolver: resolver);

final output = t.renderString({'foo': 'bar'}); // bar
// #enddocregion Partials
return output;
}

String lambdaSimpleExample() {
// #docregion LambdaSimple
final t = Template('{{# foo }}{{/ foo }}');
final lambda = (_) => 'bar';
final output = t.renderString({'foo': lambda}); // bar
// #enddocregion LambdaSimple
return output;
}

String lambdaShownExample() {
// #docregion LambdaShown
final t = Template('{{# foo }}hidden{{/ foo }}');
final lambda = (_) => 'shown';
final output = t.renderString({'foo': lambda}); // shown
// #enddocregion LambdaShown
return output;
}

String lambdaRenderExample() {
// #docregion LambdaRender
final t = Template('{{# foo }}oi{{/ foo }}');
final lambda = (LambdaContext ctx) =>
'<b>${ctx.renderString().toUpperCase()}</b>';
final output = t.renderString({'foo': lambda}); // <b>OI</b>
// #enddocregion LambdaRender
return output;
}

String lambdaRenderBarExample() {
// #docregion LambdaRenderBar
final t = Template('{{# foo }}{{bar}}{{/ foo }}');
final lambda = (LambdaContext ctx) =>
'<b>${ctx.renderString().toUpperCase()}</b>';
final output = t.renderString({'foo': lambda, 'bar': 'pub'}); // <b>PUB</b>
// #enddocregion LambdaRenderBar
return output;
}

String lambdaRenderSourceExample() {
// #docregion LambdaRenderSource
final t = Template('{{# foo }}{{bar}}{{/ foo }}');
final lambda = (LambdaContext ctx) =>
ctx.renderSource('${ctx.source} {{cmd}}');
final output = t.renderString({
'foo': lambda,
'bar': 'pub',
'cmd': 'build',
}); // pub build
// #enddocregion LambdaRenderSource
return output;
}
10 changes: 10 additions & 0 deletions third_party/packages/mustache_template/example/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: mustache_template_example
description: Example app for mustache_template package.
publish_to: none

environment:
sdk: ^3.9.0

dependencies:
mustache_template:
path: ../
2 changes: 1 addition & 1 deletion third_party/packages/mustache_template/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: mustache_template
description: A templating library that implements the Mustache template specification
repository: https://github.com/flutter/packages/tree/main/third_party/packages/mustache_template
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+mustache_template%22
version: 2.0.3
version: 2.0.4

environment:
sdk: ^3.9.0
Expand Down
2 changes: 2 additions & 0 deletions third_party/packages/mustache_template/test/all.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'example_test.dart' as example;
import 'mustache_specs.dart' as specs;
import 'mustache_test.dart' as test;
import 'parser_test.dart' as parser;

void main() {
example.main();
specs.main();
test.main();
parser.main();
Expand Down
Loading