Skip to content

Commit 2d902c0

Browse files
authored
Escape variable renders in runtime renderer (#2676)
1 parent 12adc15 commit 2d902c0

File tree

3 files changed

+29
-8
lines changed

3 files changed

+29
-8
lines changed

lib/src/mustachio/renderer_base.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// documentation.
77

88
import 'dart:collection';
9+
import 'dart:convert' show htmlEscape;
910

1011
import 'package:analyzer/file_system/file_system.dart';
1112
import 'package:meta/meta.dart';
@@ -216,7 +217,11 @@ abstract class RendererBase<T> {
216217
write(node.content);
217218
} else if (node is Variable) {
218219
var content = getFields(node);
219-
write(content);
220+
if (node.escape) {
221+
write(htmlEscape.convert(content));
222+
} else {
223+
write(content);
224+
}
220225
} else if (node is Section) {
221226
section(node);
222227
} else if (node is Partial) {

test/mustachio/aot_compiler_render_test.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,18 @@ void main() {
158158
s1: hello b1? no l1:item: 1item: 2item: 3 baz:baz is null</div>'''));
159159
});
160160

161-
test('Renderer renders a non-bool variable node', () async {
161+
test('Renderer renders a non-bool variable node, escaped', () async {
162162
var output = await renderFoo({
163163
'foo|lib/templates/html/foo.html': 'Text {{s1}}',
164-
}, '_i1.Foo()..s1 = "hello"');
165-
expect(output, equals('Text hello'));
164+
}, '_i1.Foo()..s1 = "<p>hello</p>"');
165+
expect(output, equals('Text &lt;p&gt;hello&lt;&#47;p&gt;'));
166+
});
167+
168+
test('Renderer renders a non-bool variable node, not escaped', () async {
169+
var output = await renderFoo({
170+
'foo|lib/templates/html/foo.html': 'Text {{{s1}}}',
171+
}, '_i1.Foo()..s1 = "<p>hello</p>"');
172+
expect(output, equals('Text <p>hello</p>'));
166173
});
167174

168175
test('Renderer renders a bool variable node', () async {

test/mustachio/runtime_renderer_render_test.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,21 @@ void main() {
9696
expect(propertyMap['b1'].getBool(foo), isFalse);
9797
});
9898

99-
test('Renderer renders a non-bool variable node', () async {
99+
test('Renderer renders a non-bool variable node, escaped', () async {
100100
var fooTemplateFile = getFile('/project/foo.mustache')
101101
..writeAsStringSync('Text {{s1}}');
102102
var fooTemplate = await Template.parse(fooTemplateFile);
103-
var foo = Foo()..s1 = 'hello';
104-
expect(renderFoo(foo, fooTemplate), equals('Text hello'));
103+
var foo = Foo()..s1 = '<p>hello</p>';
104+
expect(renderFoo(foo, fooTemplate),
105+
equals('Text &lt;p&gt;hello&lt;&#47;p&gt;'));
106+
});
107+
108+
test('Renderer renders a non-bool variable node, not escaped', () async {
109+
var fooTemplateFile = getFile('/project/foo.mustache')
110+
..writeAsStringSync('Text {{{s1}}}');
111+
var fooTemplate = await Template.parse(fooTemplateFile);
112+
var foo = Foo()..s1 = '<p>hello</p>';
113+
expect(renderFoo(foo, fooTemplate), equals('Text <p>hello</p>'));
105114
});
106115

107116
test('Renderer renders a bool variable node', () async {
@@ -379,7 +388,7 @@ void main() {
379388
expect(
380389
renderBar(bar, barTemplate),
381390
equals('Line 1 Partial Section 1Section 2Section 3\n'
382-
'Line 2 Partial Section Instance of \'Bar\''));
391+
'Line 2 Partial Section Instance of &#39;Bar&#39;'));
383392
});
384393

385394
test('Renderer renders a partial using a custom partial renderer', () async {

0 commit comments

Comments
 (0)