Allow `TagHelper`s inside of text/html typed script tags.

- To limit the impact of the change ensured that we only do extra work in the case that we detect a script tag with a `type` attribute.
- The parsing changes include normal HTML parsing behaviors when we detect that a script tag has a `type` attribute with value `text/html`.
- Added unit and code generation tests to validate `text/html` script tag behavior.

#502
This commit is contained in:
N. Taylor Mullen 2015-09-14 20:46:25 -07:00
parent d3835455d2
commit fb6a08d5de
8 changed files with 641 additions and 6 deletions

View File

@ -5,8 +5,8 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.AspNet.Razor.Editor;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.Editor;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Text;
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
@ -937,9 +937,17 @@ namespace Microsoft.AspNet.Razor.Parser
}
else if (string.Equals(tagName, ScriptTagName, StringComparison.OrdinalIgnoreCase))
{
CompleteTagBlockWithSpan(tagBlockWrapper, AcceptedCharacters.None, SpanKind.Markup);
if (!CurrentScriptTagExpectsHtml())
{
CompleteTagBlockWithSpan(tagBlockWrapper, AcceptedCharacters.None, SpanKind.Markup);
SkipToEndScriptAndParseCode(endTagAcceptedCharacters: AcceptedCharacters.None);
SkipToEndScriptAndParseCode(endTagAcceptedCharacters: AcceptedCharacters.None);
}
else
{
// Push the script tag onto the tag stack, it should be treated like all other HTML tags.
tags.Push(tag);
}
}
else
{

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
@ -9,6 +12,9 @@ namespace Microsoft.AspNet.Razor.Parser
{
public partial class HtmlMarkupParser
{
private static readonly char[] ValidAfterTypeAttributeNameCharacters =
new[] { ' ', '\t', '\r', '\n', '\f', '=' };
public override void ParseDocument()
{
if (Context == null)
@ -50,7 +56,7 @@ namespace Microsoft.AspNet.Razor.Parser
return;
}
// We should behave like a normal tag that has a parser escape, fall through to the normal
// We should behave like a normal tag that has a parser escape, fall through to the normal
// tag logic.
}
else if (NextIs(HtmlSymbolType.QuestionMark))
@ -79,7 +85,9 @@ namespace Microsoft.AspNet.Razor.Parser
Optional(HtmlSymbolType.ForwardSlash);
Optional(HtmlSymbolType.CloseAngle);
if (scriptTag)
// If the script tag expects javascript content then we should do minimal parsing until we reach
// the end script tag. Don't want to incorrectly parse a "var tag = '<input />';" as an HTML tag.
if (scriptTag && !CurrentScriptTagExpectsHtml())
{
Output(SpanKind.Markup);
tagBlock.Dispose();
@ -107,5 +115,54 @@ namespace Microsoft.AspNet.Razor.Parser
tagBlock.Dispose();
}
}
private bool CurrentScriptTagExpectsHtml()
{
var blockBuilder = Context.CurrentBlock;
Debug.Assert(blockBuilder != null);
var typeAttribute = blockBuilder.Children
.OfType<Block>()
.Where(block =>
block.ChunkGenerator is AttributeBlockChunkGenerator &&
block.Children.Count() >= 2)
.FirstOrDefault(IsTypeAttribute);
if (typeAttribute != null)
{
var contentValues = typeAttribute.Children
.OfType<Span>()
.Where(childSpan => childSpan.ChunkGenerator is LiteralAttributeChunkGenerator)
.Select(childSpan => childSpan.Content);
var scriptType = string.Concat(contentValues).Trim();
// Does not allow charset parameter (or any other parameters).
return string.Equals(scriptType, "text/html", StringComparison.OrdinalIgnoreCase);
}
return false;
}
private static bool IsTypeAttribute(Block block)
{
var span = block.Children.First() as Span;
if (span == null)
{
return false;
}
var trimmedStartContent = span.Content.TrimStart();
if (trimmedStartContent.StartsWith("type", StringComparison.OrdinalIgnoreCase) &&
(trimmedStartContent.Length == 4 ||
ValidAfterTypeAttributeNameCharacters.Contains(trimmedStartContent[4])))
{
return true;
}
return false;
}
}
}

View File

@ -1459,6 +1459,58 @@ namespace Microsoft.AspNet.Razor.Test.Generator
contentLength: 1),
}
},
{
"NestedScriptTagTagHelpers",
"NestedScriptTagTagHelpers.DesignTime",
DefaultPAndInputTagHelperDescriptors,
new[]
{
BuildLineMapping(
documentAbsoluteIndex: 14,
documentLineIndex: 0,
generatedAbsoluteIndex: 495,
generatedLineIndex: 15,
characterOffsetIndex: 14,
contentLength: 17),
BuildLineMapping(
documentAbsoluteIndex: 182,
documentLineIndex: 5,
generatedAbsoluteIndex: 1033,
generatedLineIndex: 35,
characterOffsetIndex: 0,
contentLength: 12),
BuildLineMapping(
documentAbsoluteIndex: 195,
documentLineIndex: 5,
documentCharacterOffsetIndex: 13,
generatedAbsoluteIndex: 1136,
generatedLineIndex: 41,
generatedCharacterOffsetIndex: 12,
contentLength: 30),
BuildLineMapping(
documentAbsoluteIndex: 339,
documentLineIndex: 7,
documentCharacterOffsetIndex: 50,
generatedAbsoluteIndex: 1385,
generatedLineIndex: 49,
generatedCharacterOffsetIndex: 6,
contentLength: 23),
BuildLineMapping(
documentAbsoluteIndex: 389,
documentLineIndex: 7,
generatedAbsoluteIndex: 1692,
generatedLineIndex: 56,
characterOffsetIndex: 100,
contentLength: 4),
BuildLineMapping(
documentAbsoluteIndex: 424,
documentLineIndex: 9,
generatedAbsoluteIndex: 1775,
generatedLineIndex: 61,
characterOffsetIndex: 0,
contentLength: 15),
}
},
};
}
}
@ -1505,7 +1557,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator
},
{ "DuplicateAttributeTagHelpers", null, DefaultPAndInputTagHelperDescriptors },
{ "DynamicAttributeTagHelpers", null, DynamicAttributeTagHelpers_Descriptors },
{ "TransitionsInTagHelperAttributes", null, DefaultPAndInputTagHelperDescriptors }
{ "TransitionsInTagHelperAttributes", null, DefaultPAndInputTagHelperDescriptors },
{ "NestedScriptTagTagHelpers", null, DefaultPAndInputTagHelperDescriptors },
};
}
}

View File

@ -18,6 +18,273 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
{
public class TagHelperParseTreeRewriterTest : TagHelperRewritingTestBase
{
public static TheoryData InvalidHtmlScriptBlockData
{
get
{
var factory = CreateDefaultSpanFactory();
var blockFactory = new BlockFactory(factory);
return new TheoryData<string, MarkupBlock>
{
{
"<script type><input /></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(factory.Markup(" type")),
factory.Markup(">")),
factory.Markup("<input />"),
blockFactory.MarkupTagBlock("</script>"))
},
{
"<script types='text/html'><input /></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "types",
prefix: new LocationTagged<string>(" types='", 7, 0, 7),
suffix: new LocationTagged<string>("'", 24, 0, 24)),
factory.Markup(" types='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 15, 0, 15),
value: new LocationTagged<string>("text/html", 15, 0, 15))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
factory.Markup("<input />"),
blockFactory.MarkupTagBlock("</script>"))
},
{
"<script type='text/html invalid'><input /></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 7, 0, 7),
suffix: new LocationTagged<string>("'", 31, 0, 31)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 14, 0, 14),
value: new LocationTagged<string>("text/html", 14, 0, 14))),
factory.Markup(" invalid").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(" ", 23, 0, 23),
value: new LocationTagged<string>("invalid", 24, 0, 24))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
factory.Markup("<input />"),
blockFactory.MarkupTagBlock("</script>"))
},
{
"<script type='text/ng-*' type='text/html'><input /></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 7, 0, 7),
suffix: new LocationTagged<string>("'", 23, 0, 23)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/ng-*").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 14, 0, 14),
value: new LocationTagged<string>("text/ng-*", 14, 0, 14))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 24, 0, 24),
suffix: new LocationTagged<string>("'", 40, 0, 40)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 31, 0, 31),
value: new LocationTagged<string>("text/html", 31, 0, 31))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
factory.Markup("<input />"),
blockFactory.MarkupTagBlock("</script>"))
},
};
}
}
[Theory]
[MemberData(nameof(InvalidHtmlScriptBlockData))]
public void TagHelperParseTreeRewriter_DoesNotUnderstandTagHelpersInInvalidHtmlTypedScriptTags(
string documentContent,
MarkupBlock expectedOutput)
{
RunParseTreeRewriterTest(documentContent, expectedOutput, "input");
}
public static TheoryData HtmlScriptBlockData
{
get
{
var factory = CreateDefaultSpanFactory();
var blockFactory = new BlockFactory(factory);
return new TheoryData<string, MarkupBlock>
{
{
"<script type='text/html'><input /></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 7, 0, 7),
suffix: new LocationTagged<string>("'", 23, 0, 23)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 14, 0, 14),
value: new LocationTagged<string>("text/html", 14, 0, 14))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
new MarkupTagHelperBlock("input", TagMode.SelfClosing),
blockFactory.MarkupTagBlock("</script>"))
},
{
"<script id='scriptTag' type='text/html' class='something'><input /></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "id",
prefix: new LocationTagged<string>(" id='", 7, 0, 7),
suffix: new LocationTagged<string>("'", 21, 0, 21)),
factory.Markup(" id='").With(SpanChunkGenerator.Null),
factory.Markup("scriptTag").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 12, 0, 12),
value: new LocationTagged<string>("scriptTag", 12, 0, 12))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 22, 0, 22),
suffix: new LocationTagged<string>("'", 38, 0, 38)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 29, 0, 29),
value: new LocationTagged<string>("text/html", 29, 0, 29))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "class",
prefix: new LocationTagged<string>(" class='", 39, 0, 39),
suffix: new LocationTagged<string>("'", 56, 0, 56)),
factory.Markup(" class='").With(SpanChunkGenerator.Null),
factory.Markup("something").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 47, 0, 47),
value: new LocationTagged<string>("something", 47, 0, 47))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
new MarkupTagHelperBlock("input", TagMode.SelfClosing),
blockFactory.MarkupTagBlock("</script>"))
},
{
"<script type='text/html'><p><script type='text/html'><input /></script></p></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 7, 0, 7),
suffix: new LocationTagged<string>("'", 23, 0, 23)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 14, 0, 14),
value: new LocationTagged<string>("text/html", 14, 0, 14))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
new MarkupTagHelperBlock("p",
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 35, 0, 35),
suffix: new LocationTagged<string>("'", 51, 0, 51)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 42, 0, 42),
value: new LocationTagged<string>("text/html", 42, 0, 42))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
new MarkupTagHelperBlock("input", TagMode.SelfClosing),
blockFactory.MarkupTagBlock("</script>")),
blockFactory.MarkupTagBlock("</script>"))
},
{
"<script type='text/html'><p><script type='text/ html'><input /></script></p></script>",
new MarkupBlock(
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 7, 0, 7),
suffix: new LocationTagged<string>("'", 23, 0, 23)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 14, 0, 14),
value: new LocationTagged<string>("text/html", 14, 0, 14))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
new MarkupTagHelperBlock("p",
new MarkupTagBlock(
factory.Markup("<script"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "type",
prefix: new LocationTagged<string>(" type='", 35, 0, 35),
suffix: new LocationTagged<string>("'", 52, 0, 52)),
factory.Markup(" type='").With(SpanChunkGenerator.Null),
factory.Markup("text/").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 42, 0, 42),
value: new LocationTagged<string>("text/", 42, 0, 42))),
factory.Markup(" html").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(" ", 47, 0, 47),
value: new LocationTagged<string>("html", 48, 0, 48))),
factory.Markup("'").With(SpanChunkGenerator.Null)),
factory.Markup(">")),
factory.Markup("<input />"),
blockFactory.MarkupTagBlock("</script>")),
blockFactory.MarkupTagBlock("</script>"))
},
};
}
}
[Theory]
[MemberData(nameof(HtmlScriptBlockData))]
public void TagHelperParseTreeRewriter_UnderstandsTagHelpersInHtmlTypedScriptTags(
string documentContent,
MarkupBlock expectedOutput)
{
RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "input");
}
[Fact]
public void Rewrite_CanHandleInvalidChildrenWithWhitespace()
{

View File

@ -0,0 +1,71 @@
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class NestedScriptTagTagHelpers
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
string __tagHelperDirectiveSyntaxHelper = null;
__tagHelperDirectiveSyntaxHelper =
#line 1 "NestedScriptTagTagHelpers.cshtml"
"something, nice"
#line default
#line hidden
;
#pragma warning restore 219
}
#line hidden
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
#line hidden
public NestedScriptTagTagHelpers()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
#line 6 "NestedScriptTagTagHelpers.cshtml"
#line default
#line hidden
#line 6 "NestedScriptTagTagHelpers.cshtml"
for(var i = 0; i < 5; i++) {
#line default
#line hidden
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
#line 8 "NestedScriptTagTagHelpers.cshtml"
__o = ViewBag.DefaultInterval;
#line default
#line hidden
__InputTagHelper.Type = "text";
__InputTagHelper2.Type = __InputTagHelper.Type;
#line 8 "NestedScriptTagTagHelpers.cshtml"
__InputTagHelper2.Checked = true;
#line default
#line hidden
#line 10 "NestedScriptTagTagHelpers.cshtml"
}
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,49 @@
// !!! Do not check in. Instead paste content into test method. !!!
var expectedLineMappings = new[]
{
BuildLineMapping(
documentAbsoluteIndex: 14,
documentLineIndex: 0,
generatedAbsoluteIndex: 495,
generatedLineIndex: 15,
characterOffsetIndex: 14,
contentLength: 17),
BuildLineMapping(
documentAbsoluteIndex: 182,
documentLineIndex: 5,
generatedAbsoluteIndex: 1033,
generatedLineIndex: 35,
characterOffsetIndex: 0,
contentLength: 12),
BuildLineMapping(
documentAbsoluteIndex: 195,
documentLineIndex: 5,
documentCharacterOffsetIndex: 13,
generatedAbsoluteIndex: 1136,
generatedLineIndex: 41,
generatedCharacterOffsetIndex: 12,
contentLength: 30),
BuildLineMapping(
documentAbsoluteIndex: 339,
documentLineIndex: 7,
documentCharacterOffsetIndex: 50,
generatedAbsoluteIndex: 1385,
generatedLineIndex: 49,
generatedCharacterOffsetIndex: 6,
contentLength: 23),
BuildLineMapping(
documentAbsoluteIndex: 389,
documentLineIndex: 7,
generatedAbsoluteIndex: 1692,
generatedLineIndex: 56,
characterOffsetIndex: 100,
contentLength: 4),
BuildLineMapping(
documentAbsoluteIndex: 424,
documentLineIndex: 9,
generatedAbsoluteIndex: 1775,
generatedLineIndex: 61,
characterOffsetIndex: 0,
contentLength: 15),
};

View File

@ -0,0 +1,114 @@
#pragma checksum "NestedScriptTagTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "9e6bc8d09df124eda650118b208b7c5e6e058f6b"
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class NestedScriptTagTagHelpers
{
#line hidden
#pragma warning disable 0414
private TagHelperContent __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
#line hidden
public NestedScriptTagTagHelpers()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner();
Instrumentation.BeginContext(33, 106, true);
WriteLiteral("\r\n<script type=\"text/html\">\r\n <div data-animation=\"fade\" class=\"randomNonTagHe" +
"lperAttribute\">\r\n ");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
Instrumentation.BeginContext(180, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
#line 6 "NestedScriptTagTagHelpers.cshtml"
#line default
#line hidden
#line 6 "NestedScriptTagTagHelpers.cshtml"
for(var i = 0; i < 5; i++) {
#line default
#line hidden
Instrumentation.BeginContext(225, 84, true);
WriteLiteral(" <script id=\"nestedScriptTag\" type=\"text/html\">\r\n " +
" ");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.StartTagOnly, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__tagHelperExecutionContext.Add(__InputTagHelper);
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
StartTagHelperWritingScope();
WriteLiteral("2000 + ");
#line 8 "NestedScriptTagTagHelpers.cshtml"
Write(ViewBag.DefaultInterval);
#line default
#line hidden
WriteLiteral(" + 1");
__tagHelperStringValueBuffer = EndTagHelperWritingScope();
__tagHelperExecutionContext.AddHtmlAttribute("data-interval", Html.Raw(__tagHelperStringValueBuffer.ToString()));
__InputTagHelper.Type = "text";
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
__InputTagHelper2.Type = __InputTagHelper.Type;
#line 8 "NestedScriptTagTagHelpers.cshtml"
__InputTagHelper2.Checked = true;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(309, 86, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(395, 29, true);
WriteLiteral("\r\n </script>\r\n");
Instrumentation.EndContext();
#line 10 "NestedScriptTagTagHelpers.cshtml"
}
#line default
#line hidden
Instrumentation.BeginContext(439, 129, true);
WriteLiteral(" <script type=\"text/javascript\">\r\n var tag = \'<input ch" +
"ecked=\"true\">\';\r\n </script>\r\n ");
Instrumentation.EndContext();
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("Hello World"));
__tagHelperExecutionContext.AddHtmlAttribute("data-delay", Html.Raw("1000"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(139, 433, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(572, 23, true);
WriteLiteral("\r\n </div>\r\n</script>");
Instrumentation.EndContext();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,16 @@
@addTagHelper "something, nice"
<script type="text/html">
<div data-animation="fade" class="randomNonTagHelperAttribute">
<p class="Hello World" data-delay="1000">
@for(var i = 0; i < 5; i++) {
<script id="nestedScriptTag" type="text/html">
<input data-interval="2000 + @ViewBag.DefaultInterval + 1" type="text" checked="true">
</script>
}
<script type="text/javascript">
var tag = '<input checked="true">';
</script>
</p>
</div>
</script>