Merge pull request #2061 from aspnet/artakm/RestrictChildrenComments
Ignoring HTML comments in tag helper's body. Updated the markup parser to be aware of HTML Comments.
This commit is contained in:
commit
a9004e503e
|
|
@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
// Special
|
||||
Comment = 8,
|
||||
Tag = 9
|
||||
Tag = 9,
|
||||
HtmlComment = 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
private const string ScriptTagName = "script";
|
||||
|
||||
private static readonly HtmlSymbol[] nonAllowedHtmlCommentEnding = new[] { HtmlSymbol.Hyphen, new HtmlSymbol("!", HtmlSymbolType.Bang), new HtmlSymbol("<", HtmlSymbolType.OpenAngle) };
|
||||
private static readonly HtmlSymbol[] singleHyphenArray = new[] { HtmlSymbol.Hyphen };
|
||||
|
||||
private static readonly char[] ValidAfterTypeAttributeNameCharacters = { ' ', '\t', '\r', '\n', '\f', '=' };
|
||||
private SourceLocation _lastTagStart = SourceLocation.Zero;
|
||||
private HtmlSymbol _bufferedOpenAngle;
|
||||
|
|
@ -492,33 +495,37 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
if (AcceptAndMoveNext())
|
||||
{
|
||||
if (CurrentSymbol.Type == HtmlSymbolType.DoubleHyphen)
|
||||
if (IsHtmlCommentAhead())
|
||||
{
|
||||
AcceptAndMoveNext();
|
||||
|
||||
Span.EditHandler.AcceptedCharacters = AcceptedCharactersInternal.Any;
|
||||
while (!EndOfFile)
|
||||
using (Context.Builder.StartBlock(BlockKindInternal.HtmlComment))
|
||||
{
|
||||
SkipToAndParseCode(HtmlSymbolType.DoubleHyphen);
|
||||
if (At(HtmlSymbolType.DoubleHyphen))
|
||||
{
|
||||
AcceptWhile(HtmlSymbolType.DoubleHyphen);
|
||||
// Accept the double-hyphen symbol at the beginning of the comment block.
|
||||
AcceptAndMoveNext();
|
||||
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.None);
|
||||
|
||||
if (At(HtmlSymbolType.Text) &&
|
||||
string.Equals(CurrentSymbol.Content, "-", StringComparison.Ordinal))
|
||||
{
|
||||
AcceptAndMoveNext();
|
||||
}
|
||||
Span.EditHandler.AcceptedCharacters = AcceptedCharactersInternal.WhiteSpace;
|
||||
while (!EndOfFile)
|
||||
{
|
||||
SkipToAndParseCode(HtmlSymbolType.DoubleHyphen);
|
||||
var lastDoubleHyphen = AcceptAllButLastDoubleHyphens();
|
||||
|
||||
if (At(HtmlSymbolType.CloseAngle))
|
||||
{
|
||||
// Output the content in the comment block as a separate markup
|
||||
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.WhiteSpace);
|
||||
|
||||
// This is the end of a comment block
|
||||
Accept(lastDoubleHyphen);
|
||||
AcceptAndMoveNext();
|
||||
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.None);
|
||||
return true;
|
||||
}
|
||||
else if (lastDoubleHyphen != null)
|
||||
{
|
||||
Accept(lastDoubleHyphen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (CurrentSymbol.Type == HtmlSymbolType.LeftBracket)
|
||||
{
|
||||
|
|
@ -537,6 +544,138 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return false;
|
||||
}
|
||||
|
||||
protected HtmlSymbol AcceptAllButLastDoubleHyphens()
|
||||
{
|
||||
var lastDoubleHyphen = CurrentSymbol;
|
||||
AcceptWhile(s =>
|
||||
{
|
||||
if (NextIs(HtmlSymbolType.DoubleHyphen))
|
||||
{
|
||||
lastDoubleHyphen = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
NextToken();
|
||||
|
||||
if (At(HtmlSymbolType.Text) && IsHyphen(CurrentSymbol))
|
||||
{
|
||||
// Doing this here to maintain the order of symbols
|
||||
if (!NextIs(HtmlSymbolType.CloseAngle))
|
||||
{
|
||||
Accept(lastDoubleHyphen);
|
||||
lastDoubleHyphen = null;
|
||||
}
|
||||
|
||||
AcceptAndMoveNext();
|
||||
}
|
||||
|
||||
return lastDoubleHyphen;
|
||||
}
|
||||
|
||||
internal static bool IsHyphen(HtmlSymbol symbol)
|
||||
{
|
||||
return symbol.Equals(HtmlSymbol.Hyphen);
|
||||
}
|
||||
|
||||
protected bool IsHtmlCommentAhead()
|
||||
{
|
||||
/*
|
||||
* From HTML5 Specification, available at http://www.w3.org/TR/html52/syntax.html#comments
|
||||
*
|
||||
* Comments must have the following format:
|
||||
* 1. The string "<!--"
|
||||
* 2. Optionally, text, with the additional restriction that the text
|
||||
* 2.1 must not start with the string ">" nor start with the string "->"
|
||||
* 2.2 nor contain the strings
|
||||
* 2.2.1 "<!--"
|
||||
* 2.2.2 "-->" // As we will be treating this as a comment ending, there is no need to handle this case at all.
|
||||
* 2.2.3 "--!>"
|
||||
* 2.3 nor end with the string "<!-".
|
||||
* 3. The string "-->"
|
||||
*
|
||||
* */
|
||||
|
||||
if (CurrentSymbol.Type != HtmlSymbolType.DoubleHyphen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check condition 2.1
|
||||
if (NextIs(HtmlSymbolType.CloseAngle) || NextIs(next => IsHyphen(next) && NextIs(HtmlSymbolType.CloseAngle)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check condition 2.2
|
||||
var isValidComment = false;
|
||||
LookaheadUntil((symbol, prevSymbols) =>
|
||||
{
|
||||
if (symbol.Type == HtmlSymbolType.DoubleHyphen)
|
||||
{
|
||||
if (NextIs(HtmlSymbolType.CloseAngle))
|
||||
{
|
||||
// Check condition 2.3: We're at the end of a comment. Check to make sure the text ending is allowed.
|
||||
isValidComment = !IsCommentContentEndingInvalid(prevSymbols);
|
||||
return true;
|
||||
}
|
||||
else if (NextIs(ns => IsHyphen(ns) && NextIs(HtmlSymbolType.CloseAngle)))
|
||||
{
|
||||
// Check condition 2.3: we're at the end of a comment, which has an extra dash.
|
||||
// Need to treat the dash as part of the content and check the ending.
|
||||
// However, that case would have already been checked as part of check from 2.2.1 which
|
||||
// would already fail this iteration and we wouldn't get here
|
||||
isValidComment = true;
|
||||
return true;
|
||||
}
|
||||
else if (NextIs(ns => ns.Type == HtmlSymbolType.Bang && NextIs(HtmlSymbolType.CloseAngle)))
|
||||
{
|
||||
// This is condition 2.2.3
|
||||
isValidComment = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (symbol.Type == HtmlSymbolType.OpenAngle)
|
||||
{
|
||||
// Checking condition 2.2.1
|
||||
if (NextIs(ns => ns.Type == HtmlSymbolType.Bang && NextIs(HtmlSymbolType.DoubleHyphen)))
|
||||
{
|
||||
isValidComment = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return isValidComment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies, that the sequence doesn't end with the "<!-" HtmlSymbols. Note, the first symbol is an opening bracket symbol
|
||||
/// </summary>
|
||||
internal static bool IsCommentContentEndingInvalid(IEnumerable<HtmlSymbol> sequence)
|
||||
{
|
||||
var reversedSequence = sequence.Reverse();
|
||||
var index = 0;
|
||||
foreach (var item in reversedSequence)
|
||||
{
|
||||
if (!item.Equals(nonAllowedHtmlCommentEnding[index++]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index == nonAllowedHtmlCommentEnding.Length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CData()
|
||||
{
|
||||
if (CurrentSymbol.Type == HtmlSymbolType.Text && string.Equals(CurrentSymbol.Content, "cdata", StringComparison.OrdinalIgnoreCase))
|
||||
|
|
@ -1474,8 +1613,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
// Checking to see if we meet the conditions of a special '!' tag: <!DOCTYPE, <![CDATA[, <!--.
|
||||
if (!IsBangEscape(lookahead: 1))
|
||||
{
|
||||
if (Lookahead(2)?.Type == HtmlSymbolType.DoubleHyphen)
|
||||
{
|
||||
Output(SpanKindInternal.Markup);
|
||||
}
|
||||
|
||||
AcceptAndMoveNext(); // Accept '<'
|
||||
BangTag();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
internal class HtmlSymbol : SymbolBase<HtmlSymbolType>
|
||||
{
|
||||
internal static readonly HtmlSymbol Hyphen = new HtmlSymbol("-", HtmlSymbolType.Text);
|
||||
|
||||
public HtmlSymbol(string content, HtmlSymbolType type)
|
||||
: base(content, type, RazorDiagnostic.EmptyArray)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -490,20 +490,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
if (HasAllowedChildren())
|
||||
{
|
||||
var content = child.Content;
|
||||
if (!string.IsNullOrWhiteSpace(content))
|
||||
var isDisallowedContent = true;
|
||||
if (_featureFlags.AllowHtmlCommentsInTagHelpers)
|
||||
{
|
||||
var trimmedStart = content.TrimStart();
|
||||
var whitespace = content.Substring(0, content.Length - trimmedStart.Length);
|
||||
var errorStart = SourceLocationTracker.Advance(child.Start, whitespace);
|
||||
var length = trimmedStart.TrimEnd().Length;
|
||||
var allowedChildren = _currentTagHelperTracker.AllowedChildren;
|
||||
var allowedChildrenString = string.Join(", ", allowedChildren);
|
||||
errorSink.OnError(
|
||||
RazorDiagnosticFactory.CreateTagHelper_CannotHaveNonTagContent(
|
||||
new SourceSpan(errorStart, length),
|
||||
_currentTagHelperTracker.TagName,
|
||||
allowedChildrenString));
|
||||
isDisallowedContent = !IsComment(child) && child.Kind != SpanKindInternal.Transition && child.Kind != SpanKindInternal.Code;
|
||||
}
|
||||
|
||||
if (isDisallowedContent)
|
||||
{
|
||||
var content = child.Content;
|
||||
if (!string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
var trimmedStart = content.TrimStart();
|
||||
var whitespace = content.Substring(0, content.Length - trimmedStart.Length);
|
||||
var errorStart = SourceLocationTracker.Advance(child.Start, whitespace);
|
||||
var length = trimmedStart.TrimEnd().Length;
|
||||
var allowedChildren = _currentTagHelperTracker.AllowedChildren;
|
||||
var allowedChildrenString = string.Join(", ", allowedChildren);
|
||||
errorSink.OnError(
|
||||
RazorDiagnosticFactory.CreateTagHelper_CannotHaveNonTagContent(
|
||||
new SourceSpan(errorStart, length),
|
||||
_currentTagHelperTracker.TagName,
|
||||
allowedChildrenString));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -817,6 +826,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return relevantSymbol.Type == HtmlSymbolType.ForwardSlash;
|
||||
}
|
||||
|
||||
internal static bool IsComment(Span span)
|
||||
{
|
||||
Block currentBlock = span.Parent;
|
||||
while (currentBlock != null && currentBlock.Type != BlockKindInternal.Comment && currentBlock.Type != BlockKindInternal.HtmlComment)
|
||||
{
|
||||
currentBlock = currentBlock.Parent;
|
||||
}
|
||||
|
||||
return currentBlock != null;
|
||||
}
|
||||
|
||||
|
||||
private static void EnsureTagBlock(Block tagBlock)
|
||||
{
|
||||
Debug.Assert(tagBlock.Type == BlockKindInternal.Tag);
|
||||
|
|
|
|||
|
|
@ -109,6 +109,52 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return symbols[count];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks forward until the specified condition is met.
|
||||
/// </summary>
|
||||
/// <param name="condition">A predicate accepting the symbol being evaluated and the list of symbols which have been looped through.</param>
|
||||
/// <returns>true, if the condition was met. false - if the condition wasn't met and the last symbol has already been processed.</returns>
|
||||
/// <remarks>The list of previous symbols is passed in the reverse order. So the last processed element will be the first one in the list.</remarks>
|
||||
protected bool LookaheadUntil(Func<TSymbol, IEnumerable<TSymbol>, bool> condition)
|
||||
{
|
||||
if (condition == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(condition));
|
||||
}
|
||||
|
||||
var matchFound = false;
|
||||
|
||||
var symbols = new List<TSymbol>();
|
||||
symbols.Add(CurrentSymbol);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!NextToken())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
symbols.Add(CurrentSymbol);
|
||||
if (condition(CurrentSymbol, symbols))
|
||||
{
|
||||
matchFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore Tokenizer's location to where it was pointing before the look-ahead.
|
||||
for (var i = symbols.Count - 1; i >= 0; i--)
|
||||
{
|
||||
PutBack(symbols[i]);
|
||||
}
|
||||
|
||||
// The PutBacks above will set CurrentSymbol to null. EnsureCurrent will set our CurrentSymbol to the
|
||||
// next symbol.
|
||||
EnsureCurrent();
|
||||
|
||||
return matchFound;
|
||||
}
|
||||
|
||||
protected internal bool NextToken()
|
||||
{
|
||||
PreviousSymbol = CurrentSymbol;
|
||||
|
|
@ -254,12 +300,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
protected internal bool NextIs(Func<TSymbol, bool> condition)
|
||||
{
|
||||
var cur = CurrentSymbol;
|
||||
NextToken();
|
||||
var result = condition(CurrentSymbol);
|
||||
PutCurrentBack();
|
||||
PutBack(cur);
|
||||
EnsureCurrent();
|
||||
return result;
|
||||
if (NextToken())
|
||||
{
|
||||
var result = condition(CurrentSymbol);
|
||||
PutCurrentBack();
|
||||
PutBack(cur);
|
||||
EnsureCurrent();
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
PutBack(cur);
|
||||
EnsureCurrent();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected internal bool Was(TSymbolType type)
|
||||
|
|
|
|||
|
|
@ -8,26 +8,33 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
public static RazorParserFeatureFlags Create(RazorLanguageVersion version)
|
||||
{
|
||||
var allowMinimizedBooleanTagHelperAttributes = false;
|
||||
var allowHtmlCommentsInTagHelpers = false;
|
||||
|
||||
if (version.CompareTo(RazorLanguageVersion.Version_2_1) >= 0)
|
||||
{
|
||||
// Added in 2.1
|
||||
allowMinimizedBooleanTagHelperAttributes = true;
|
||||
allowHtmlCommentsInTagHelpers = true;
|
||||
}
|
||||
|
||||
return new DefaultRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes);
|
||||
return new DefaultRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes, allowHtmlCommentsInTagHelpers);
|
||||
}
|
||||
|
||||
public abstract bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||
|
||||
public abstract bool AllowHtmlCommentsInTagHelpers { get; }
|
||||
|
||||
private class DefaultRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||
{
|
||||
public DefaultRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes)
|
||||
public DefaultRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelpers)
|
||||
{
|
||||
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelpers;
|
||||
}
|
||||
|
||||
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||
|
||||
public override bool AllowHtmlCommentsInTagHelpers { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
|||
|
||||
// Special
|
||||
Comment,
|
||||
Tag
|
||||
Tag,
|
||||
|
||||
HtmlComment
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
// Act & Assert
|
||||
ParseDocumentTest(
|
||||
"@section foo "
|
||||
"@section foo "
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
|
|
@ -606,7 +606,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
|
||||
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!-- -->")),
|
||||
BlockFactory.HtmlCommentBlock(" "),
|
||||
Factory.EmptyHtml()),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
|
@ -630,7 +631,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
|
||||
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!-- > \" '-->")),
|
||||
BlockFactory.HtmlCommentBlock(" > \" '"),
|
||||
Factory.EmptyHtml()),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
|
@ -655,7 +657,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.Markup(Environment.NewLine),
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("<a" + Environment.NewLine)),
|
||||
Factory.Markup("<!-- > \" '-->")),
|
||||
BlockFactory.HtmlCommentBlock(" > \" '"),
|
||||
Factory.EmptyHtml()),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.Code(Environment.NewLine).AsStatement().AutoCompleteWith(null),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.Markup("<!-- Hello, I'm a comment that shouldn't break razor --->").Accepts(AcceptedCharactersInternal.None),
|
||||
BlockFactory.HtmlCommentBlock(" Hello, I'm a comment that shouldn't break razor -"),
|
||||
Factory.Markup(Environment.NewLine).Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||
|
|
@ -333,7 +333,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
[Fact]
|
||||
public void ParseBlockSupportsCommentAsBlock()
|
||||
{
|
||||
SingleSpanBlockTest("<!-- foo -->", BlockKindInternal.Markup, SpanKindInternal.Markup, acceptedCharacters: AcceptedCharactersInternal.None);
|
||||
ParseBlockTest("<!-- foo -->", new MarkupBlock(BlockFactory.HtmlCommentBlock(" foo ")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsCommentWithExtraDashAsBlock()
|
||||
{
|
||||
ParseBlockTest("<!-- foo --->", new MarkupBlock(BlockFactory.HtmlCommentBlock(" foo -")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -344,8 +350,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupTagBlock(
|
||||
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.Markup("bar"),
|
||||
Factory.Markup("<!-- zoop -->").Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Markup("baz"),
|
||||
BlockFactory.HtmlCommentBlock(" zoop "),
|
||||
Factory.Markup("baz").Accepts(AcceptedCharactersInternal.None),
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
||||
}
|
||||
|
|
@ -355,7 +361,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
get
|
||||
{
|
||||
var factory = new SpanFactory();
|
||||
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
return new TheoryData<string, MarkupBlock>
|
||||
{
|
||||
{
|
||||
|
|
@ -363,7 +369,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||
factory.Markup("<!--- Hello World --->").Accepts(AcceptedCharactersInternal.None),
|
||||
blockFactory.HtmlCommentBlock("- Hello World -"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||
},
|
||||
|
|
@ -372,7 +378,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||
factory.Markup("<!---- Hello World ---->").Accepts(AcceptedCharactersInternal.None),
|
||||
blockFactory.HtmlCommentBlock("-- Hello World --"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||
},
|
||||
|
|
@ -381,7 +387,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||
factory.Markup("<!----- Hello World ----->").Accepts(AcceptedCharactersInternal.None),
|
||||
blockFactory.HtmlCommentBlock("--- Hello World ---"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||
},
|
||||
|
|
@ -390,7 +396,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||
factory.Markup("<!----- Hello < --- > World </div> ----->").Accepts(AcceptedCharactersInternal.None),
|
||||
blockFactory.HtmlCommentBlock("--- Hello < --- > World </div> ---"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||
},
|
||||
|
|
@ -410,19 +416,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
[Fact]
|
||||
public void ParseBlockProperlyBalancesCommentStartAndEndTags()
|
||||
{
|
||||
SingleSpanBlockTest("<!--<foo></bar>-->", BlockKindInternal.Markup, SpanKindInternal.Markup, acceptedCharacters: AcceptedCharactersInternal.None);
|
||||
ParseBlockTest("<!--<foo></bar>-->", new MarkupBlock(BlockFactory.HtmlCommentBlock("<foo></bar>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesAtEOFWhenParsingComment()
|
||||
{
|
||||
SingleSpanBlockTest("<!--<foo>", "<!--<foo>", BlockKindInternal.Markup, SpanKindInternal.Markup);
|
||||
ParseBlockTest(
|
||||
"<!--<foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!--<foo>").Accepts(AcceptedCharactersInternal.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockOnlyTerminatesCommentOnFullEndSequence()
|
||||
{
|
||||
SingleSpanBlockTest("<!--<foo>--</bar>-->", BlockKindInternal.Markup, SpanKindInternal.Markup, acceptedCharacters: AcceptedCharactersInternal.None);
|
||||
ParseBlockTest("<!--<foo>--</bar>-->", new MarkupBlock(BlockFactory.HtmlCommentBlock("<foo>--</bar>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -432,8 +441,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.Markup("<!--<foo></bar-->").Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Markup("-->"),
|
||||
BlockFactory.HtmlCommentBlock("<foo></bar"),
|
||||
Factory.Markup("-->").Accepts(AcceptedCharactersInternal.None),
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,7 +214,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
[Fact]
|
||||
public void ParseDocumentReturnsOneMarkupSegmentIfNoCodeBlocksEncountered()
|
||||
{
|
||||
SingleSpanDocumentTest("Foo Baz<!--Foo-->Bar<!--F> Qux", BlockKindInternal.Markup, SpanKindInternal.Markup);
|
||||
ParseDocumentTest("Foo Baz<!--Foo-->Bar<!--F> Qux",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("Foo Baz"),
|
||||
BlockFactory.HtmlCommentBlock("Foo"),
|
||||
Factory.Markup("Bar"),
|
||||
Factory.Markup("<!--F> Qux")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,226 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Test.Legacy
|
||||
{
|
||||
public class HtmlMarkupParserTests
|
||||
{
|
||||
private static readonly HtmlSymbol doubleHyphenSymbol = new HtmlSymbol("--", HtmlSymbolType.DoubleHyphen);
|
||||
|
||||
public static IEnumerable<object[]> NonDashSymbols
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new[] { new HtmlSymbol("--", HtmlSymbolType.DoubleHyphen) };
|
||||
yield return new[] { new HtmlSymbol("asdf", HtmlSymbolType.Text) };
|
||||
yield return new[] { new HtmlSymbol(">", HtmlSymbolType.CloseAngle) };
|
||||
yield return new[] { new HtmlSymbol("<", HtmlSymbolType.OpenAngle) };
|
||||
yield return new[] { new HtmlSymbol("!", HtmlSymbolType.Bang) };
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(NonDashSymbols))]
|
||||
public void IsHyphen_ReturnsFalseForNonDashSymbol(object symbol)
|
||||
{
|
||||
// Arrange
|
||||
var convertedSymbol = (HtmlSymbol)symbol;
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(HtmlMarkupParser.IsHyphen(convertedSymbol));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHyphen_ReturnsTrueForADashSymbol()
|
||||
{
|
||||
// Arrange
|
||||
var dashSymbol = new HtmlSymbol("-", HtmlSymbolType.Text);
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(HtmlMarkupParser.IsHyphen(dashSymbol));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AcceptAllButLastDoubleHypens_ReturnsTheOnlyDoubleHyphenSymbol()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-->");
|
||||
|
||||
// Act
|
||||
var symbol = sut.AcceptAllButLastDoubleHyphens();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(doubleHyphenSymbol, symbol);
|
||||
Assert.True(sut.At(HtmlSymbolType.CloseAngle));
|
||||
Assert.Equal(doubleHyphenSymbol, sut.PreviousSymbol);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AcceptAllButLastDoubleHypens_ReturnsTheDoubleHyphenSymbolAfterAcceptingTheDash()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("--->");
|
||||
|
||||
// Act
|
||||
var symbol = sut.AcceptAllButLastDoubleHyphens();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(doubleHyphenSymbol, symbol);
|
||||
Assert.True(sut.At(HtmlSymbolType.CloseAngle));
|
||||
Assert.True(HtmlMarkupParser.IsHyphen(sut.PreviousSymbol));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsTrueForEmptyCommentTag()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("---->");
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsTrueForValidCommentTag()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-- Some comment content in here -->");
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsTrueForValidCommentTagWithExtraDashesAtClosingTag()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-- Some comment content in here ----->");
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsFalseForContentWithBadEndingAndExtraDash()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-- Some comment content in here <!--->");
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsTrueForValidCommentTagWithExtraInfoAfter()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-- comment --> the first part is a valid comment without the Open angle and bang symbols");
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsFalseForNotClosedComment()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-- not closed comment");
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsFalseForCommentWithoutLastClosingAngle()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-- not closed comment--");
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsHtmlCommentAhead_ReturnsTrueForCommentWithCodeInside()
|
||||
{
|
||||
// Arrange
|
||||
var sut = CreateTestParserForContent("-- not closed @DateTime.Now comment-->");
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(sut.IsHtmlCommentAhead());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsCommentContentEndingInvalid_ReturnsFalseForAllowedContent()
|
||||
{
|
||||
// Arrange
|
||||
var expectedSymbol1 = new HtmlSymbol("a", HtmlSymbolType.Text);
|
||||
var sequence = Enumerable.Range((int)'a', 26).Select(item => new HtmlSymbol(((char)item).ToString(), HtmlSymbolType.Text));
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(HtmlMarkupParser.IsCommentContentEndingInvalid(sequence));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsCommentContentEndingInvalid_ReturnsTrueForDisallowedContent()
|
||||
{
|
||||
// Arrange
|
||||
var expectedSymbol1 = new HtmlSymbol("a", HtmlSymbolType.Text);
|
||||
var sequence = new[] { new HtmlSymbol("<", HtmlSymbolType.OpenAngle), new HtmlSymbol("!", HtmlSymbolType.Bang), new HtmlSymbol("-", HtmlSymbolType.Text) };
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(HtmlMarkupParser.IsCommentContentEndingInvalid(sequence));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsCommentContentEndingInvalid_ReturnsFalseForEmptyContent()
|
||||
{
|
||||
// Arrange
|
||||
var expectedSymbol1 = new HtmlSymbol("a", HtmlSymbolType.Text);
|
||||
var sequence = Array.Empty<HtmlSymbol>();
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(HtmlMarkupParser.IsCommentContentEndingInvalid(sequence));
|
||||
}
|
||||
|
||||
private class TestHtmlMarkupParser : HtmlMarkupParser
|
||||
{
|
||||
public new HtmlSymbol PreviousSymbol
|
||||
{
|
||||
get => base.PreviousSymbol;
|
||||
}
|
||||
|
||||
public new bool IsHtmlCommentAhead()
|
||||
{
|
||||
return base.IsHtmlCommentAhead();
|
||||
}
|
||||
|
||||
public TestHtmlMarkupParser(ParserContext context) : base(context)
|
||||
{
|
||||
this.EnsureCurrent();
|
||||
}
|
||||
|
||||
public new HtmlSymbol AcceptAllButLastDoubleHyphens()
|
||||
{
|
||||
return base.AcceptAllButLastDoubleHyphens();
|
||||
}
|
||||
|
||||
public override void BuildSpan(SpanBuilder span, SourceLocation start, string content)
|
||||
{
|
||||
base.BuildSpan(span, start, content);
|
||||
}
|
||||
}
|
||||
|
||||
private static TestHtmlMarkupParser CreateTestParserForContent(string content)
|
||||
{
|
||||
var source = TestRazorSourceDocument.Create(content);
|
||||
var options = RazorParserOptions.CreateDefault();
|
||||
var context = new ParserContext(source, options);
|
||||
|
||||
return new TestHtmlMarkupParser(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
ParseBlockTest("<!--Foo--> Bar",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!--Foo-->").Accepts(AcceptedCharactersInternal.None),
|
||||
BlockFactory.HtmlCommentBlock("Foo"),
|
||||
Factory.Markup(" ").Accepts(AcceptedCharactersInternal.None)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,13 +112,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.Markup("<!-- "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||
Factory.Markup(" -->").Accepts(AcceptedCharactersInternal.None),
|
||||
BlockFactory.HtmlCommentBlock(Factory, f => new SyntaxTreeNode[] {
|
||||
f.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace),
|
||||
new ExpressionBlock(
|
||||
f.CodeTransition(),
|
||||
f.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||
f.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace) }),
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2950,7 +2950,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
intType),
|
||||
RazorDiagnosticFactory.CreateParsing_TagHelperIndexerAttributeNameMustIncludeKey(
|
||||
new SourceSpan(7, 0, 7, 11),
|
||||
"int-prefix-",
|
||||
"int-prefix-",
|
||||
"input"),
|
||||
}
|
||||
},
|
||||
|
|
@ -2973,7 +2973,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
stringType),
|
||||
RazorDiagnosticFactory.CreateParsing_TagHelperIndexerAttributeNameMustIncludeKey(
|
||||
new SourceSpan(7, 0, 7, 14),
|
||||
"string-prefix-",
|
||||
"string-prefix-",
|
||||
"input"),
|
||||
}
|
||||
},
|
||||
|
|
@ -3638,7 +3638,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
RazorDiagnosticFactory.CreateTagHelper_EmptyBoundAttribute(
|
||||
new SourceSpan(7, 0, 7, 21),
|
||||
"bound-required-string",
|
||||
"input",
|
||||
"input",
|
||||
stringType),
|
||||
}
|
||||
},
|
||||
|
|
@ -3962,7 +3962,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.Build(),
|
||||
};
|
||||
|
||||
var featureFlags = new TestRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes: false);
|
||||
var featureFlags = new TestRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes: false, allowHtmlCommentsInTagHelper: false);
|
||||
|
||||
var expectedOutput = new MarkupBlock(
|
||||
new MarkupTagHelperBlock(
|
||||
|
|
@ -3994,12 +3994,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
private class TestRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||
{
|
||||
public TestRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes)
|
||||
public TestRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelper)
|
||||
{
|
||||
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelper;
|
||||
}
|
||||
|
||||
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||
|
||||
public override bool AllowHtmlCommentsInTagHelpers { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
rule
|
||||
.RequireTagName("input")
|
||||
.RequireTagStructure(TagStructure.WithoutEndTag))
|
||||
|
|
@ -371,7 +371,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
|
||||
.Build(),
|
||||
};
|
||||
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(
|
||||
descriptors,
|
||||
|
|
@ -793,7 +793,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
TagHelperDescriptorBuilder.Create("StrongTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
rule
|
||||
.RequireTagName("strong")
|
||||
.RequireAttributeDescriptor(attribute => attribute.Name("required")))
|
||||
|
|
@ -830,7 +830,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
|
||||
.Build(),
|
||||
TagHelperDescriptorBuilder.Create("BRTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
rule
|
||||
.RequireTagName("br")
|
||||
.RequireTagStructure(TagStructure.WithoutEndTag))
|
||||
|
|
@ -1108,6 +1108,243 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
EvaluateData(descriptors, documentContent, (MarkupBlock)expectedOutput, (RazorDiagnostic[])expectedErrors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rewrite_AllowsSimpleHtmlCommentsAsChildren()
|
||||
{
|
||||
// Arrange
|
||||
IEnumerable<string> allowedChildren = new List<string> { "b" };
|
||||
string literal = "asdf";
|
||||
string commentOutput = "Hello World";
|
||||
string expectedOutput = $"<p><b>{literal}</b><!--{commentOutput}--></p>";
|
||||
|
||||
var pTagHelperBuilder = TagHelperDescriptorBuilder
|
||||
.Create("PTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("p"));
|
||||
foreach (var childTag in allowedChildren)
|
||||
{
|
||||
pTagHelperBuilder.AllowChildTag(childTag);
|
||||
}
|
||||
|
||||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
pTagHelperBuilder.Build()
|
||||
};
|
||||
|
||||
var factory = new SpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
var expectedMarkup = new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
blockFactory.MarkupTagBlock("<b>"),
|
||||
factory.Markup(literal),
|
||||
blockFactory.MarkupTagBlock("</b>"),
|
||||
blockFactory.HtmlCommentBlock(commentOutput)));
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(
|
||||
descriptors,
|
||||
expectedOutput,
|
||||
expectedMarkup,
|
||||
Array.Empty<RazorDiagnostic>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rewrite_DoesntAllowSimpleHtmlCommentsAsChildrenWhenFeatureFlagIsOff()
|
||||
{
|
||||
// Arrange
|
||||
Func<string, string, string, int, int, RazorDiagnostic> nestedTagError =
|
||||
(childName, parentName, allowed, location, length) =>
|
||||
RazorDiagnosticFactory.CreateTagHelper_InvalidNestedTag(
|
||||
new SourceSpan(absoluteIndex: location, lineIndex: 0, characterIndex: location, length: length), childName, parentName, allowed);
|
||||
Func<string, string, int, int, RazorDiagnostic> nestedContentError =
|
||||
(parentName, allowed, location, length) =>
|
||||
RazorDiagnosticFactory.CreateTagHelper_CannotHaveNonTagContent(
|
||||
new SourceSpan(absoluteIndex: location, lineIndex: 0, characterIndex: location, length: length), parentName, allowed);
|
||||
|
||||
IEnumerable<string> allowedChildren = new List<string> { "b" };
|
||||
string comment1 = "Hello";
|
||||
string expectedOutput = $"<p><!--{comment1}--></p>";
|
||||
|
||||
var pTagHelperBuilder = TagHelperDescriptorBuilder
|
||||
.Create("PTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("p"));
|
||||
foreach (var childTag in allowedChildren)
|
||||
{
|
||||
pTagHelperBuilder.AllowChildTag(childTag);
|
||||
}
|
||||
|
||||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
pTagHelperBuilder.Build()
|
||||
};
|
||||
|
||||
var factory = new SpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
var expectedMarkup = new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
blockFactory.HtmlCommentBlock(comment1)));
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(
|
||||
descriptors,
|
||||
expectedOutput,
|
||||
expectedMarkup,
|
||||
new[]
|
||||
{
|
||||
nestedContentError("p", "b", 3, 4),
|
||||
nestedContentError("p", "b", 7, 5),
|
||||
nestedContentError("p", "b", 12, 3),
|
||||
},
|
||||
featureFlags: RazorParserFeatureFlags.Create(RazorLanguageVersion.Version_2_0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rewrite_FailsForContentWithCommentsAsChildren()
|
||||
{
|
||||
// Arrange
|
||||
Func<string, string, string, int, int, RazorDiagnostic> nestedTagError =
|
||||
(childName, parentName, allowed, location, length) =>
|
||||
RazorDiagnosticFactory.CreateTagHelper_InvalidNestedTag(
|
||||
new SourceSpan(absoluteIndex: location, lineIndex: 0, characterIndex: location, length: length), childName, parentName, allowed);
|
||||
Func<string, string, int, int, RazorDiagnostic> nestedContentError =
|
||||
(parentName, allowed, location, length) =>
|
||||
RazorDiagnosticFactory.CreateTagHelper_CannotHaveNonTagContent(
|
||||
new SourceSpan(absoluteIndex: location, lineIndex: 0, characterIndex: location, length: length), parentName, allowed);
|
||||
|
||||
IEnumerable<string> allowedChildren = new List<string> { "b" };
|
||||
string comment1 = "Hello";
|
||||
string literal = "asdf";
|
||||
string comment2 = "World";
|
||||
string expectedOutput = $"<p><!--{comment1}-->{literal}<!--{comment2}--></p>";
|
||||
|
||||
var pTagHelperBuilder = TagHelperDescriptorBuilder
|
||||
.Create("PTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("p"));
|
||||
foreach (var childTag in allowedChildren)
|
||||
{
|
||||
pTagHelperBuilder.AllowChildTag(childTag);
|
||||
}
|
||||
|
||||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
pTagHelperBuilder.Build()
|
||||
};
|
||||
|
||||
var factory = new SpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
var expectedMarkup = new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
blockFactory.HtmlCommentBlock(comment1),
|
||||
factory.Markup(literal),
|
||||
blockFactory.HtmlCommentBlock(comment2)));
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(
|
||||
descriptors,
|
||||
expectedOutput,
|
||||
expectedMarkup,
|
||||
new[]
|
||||
{
|
||||
nestedContentError("p", "b", 15, 4),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rewrite_AllowsRazorCommentsAsChildren()
|
||||
{
|
||||
// Arrange
|
||||
IEnumerable<string> allowedChildren = new List<string> { "b" };
|
||||
string literal = "asdf";
|
||||
string commentOutput = $"@*{literal}*@";
|
||||
string expectedOutput = $"<p><b>{literal}</b>{commentOutput}</p>";
|
||||
|
||||
var pTagHelperBuilder = TagHelperDescriptorBuilder
|
||||
.Create("PTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("p"));
|
||||
foreach (var childTag in allowedChildren)
|
||||
{
|
||||
pTagHelperBuilder.AllowChildTag(childTag);
|
||||
}
|
||||
|
||||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
pTagHelperBuilder.Build()
|
||||
};
|
||||
|
||||
var factory = new SpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
var expectedMarkup = new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
blockFactory.MarkupTagBlock("<b>"),
|
||||
factory.Markup(literal),
|
||||
blockFactory.MarkupTagBlock("</b>"),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition).Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Span(SpanKindInternal.Comment, new HtmlSymbol(literal, HtmlSymbolType.RazorComment)).Accepts(AcceptedCharactersInternal.Any),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition).Accepts(AcceptedCharactersInternal.None))));
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(
|
||||
descriptors,
|
||||
expectedOutput,
|
||||
expectedMarkup,
|
||||
Array.Empty<RazorDiagnostic>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rewrite_AllowsRazorMarkupInHtmlComment()
|
||||
{
|
||||
// Arrange
|
||||
IEnumerable<string> allowedChildren = new List<string> { "b" };
|
||||
string literal = "asdf";
|
||||
string part1 = "Hello ";
|
||||
string part2 = "World";
|
||||
string commentStart = "<!--";
|
||||
string commentEnd = "-->";
|
||||
string expectedOutput = $"<p><b>{literal}</b>{commentStart}{part1}@{part2}{commentEnd}</p>";
|
||||
|
||||
var pTagHelperBuilder = TagHelperDescriptorBuilder
|
||||
.Create("PTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("p"));
|
||||
foreach (var childTag in allowedChildren)
|
||||
{
|
||||
pTagHelperBuilder.AllowChildTag(childTag);
|
||||
}
|
||||
|
||||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
pTagHelperBuilder.Build()
|
||||
};
|
||||
|
||||
var factory = new SpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
var expectedMarkup = new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
blockFactory.MarkupTagBlock("<b>"),
|
||||
factory.Markup(literal),
|
||||
blockFactory.MarkupTagBlock("</b>"),
|
||||
BlockFactory.HtmlCommentBlock(factory, f => new SyntaxTreeNode[] {
|
||||
f.Markup(part1).Accepts(AcceptedCharactersInternal.WhiteSpace),
|
||||
new ExpressionBlock(
|
||||
f.CodeTransition(),
|
||||
f.Code(part2)
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)) })));
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(
|
||||
descriptors,
|
||||
expectedOutput,
|
||||
expectedMarkup,
|
||||
Array.Empty<RazorDiagnostic>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rewrite_UnderstandsNullTagNameWithAllowedChildrenForCatchAll()
|
||||
{
|
||||
|
|
@ -1173,7 +1410,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
rule
|
||||
.RequireTagName("input")
|
||||
.RequireTagStructure(TagStructure.WithoutEndTag))
|
||||
|
|
@ -1646,7 +1883,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
TagHelperDescriptorBuilder.Create("pTagHelper", "SomeAssembly")
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
.TagMatchingRuleDescriptor(rule =>
|
||||
rule
|
||||
.RequireTagName("p")
|
||||
.RequireAttributeDescriptor(attribute => attribute.Name("class")))
|
||||
|
|
@ -3901,14 +4138,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
get
|
||||
{
|
||||
var factory = new SpanFactory();
|
||||
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
yield return new object[]
|
||||
{
|
||||
"<foo><!-- Hello World --></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<!-- Hello World -->"),
|
||||
blockFactory.HtmlCommentBlock (" Hello World "),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
|
|
@ -3918,13 +4155,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<!-- "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||
factory.Markup(" -->"),
|
||||
BlockFactory.HtmlCommentBlock(factory, f=> new SyntaxTreeNode[]{
|
||||
f.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace),
|
||||
new ExpressionBlock(
|
||||
f.CodeTransition(),
|
||||
f.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||
factory.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace) }),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
|
|
@ -4000,8 +4238,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||
factory.Markup(" ]]>"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -56,6 +56,85 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Assert.Equal("pre-existing values", tokenizer.Buffer.ToString(), StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LookaheadUntil_PassesThePreviousSymbolsInTheSameOrder()
|
||||
{
|
||||
// Arrange
|
||||
var tokenizer = CreateContentTokenizer("asdf--fvd--<");
|
||||
|
||||
// Act
|
||||
var i = 3;
|
||||
IEnumerable<HtmlSymbol> previousSymbols = null;
|
||||
var symbolFound = tokenizer.LookaheadUntil((s, p) =>
|
||||
{
|
||||
previousSymbols = p;
|
||||
return --i == 0;
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.Equal(4, previousSymbols.Count());
|
||||
|
||||
// For the very first element, there will be no previous items, so null is expected
|
||||
var orderIndex = 0;
|
||||
Assert.Null(previousSymbols.ElementAt(orderIndex++));
|
||||
Assert.Equal(new HtmlSymbol("asdf", HtmlSymbolType.Text), previousSymbols.ElementAt(orderIndex++));
|
||||
Assert.Equal(new HtmlSymbol("--", HtmlSymbolType.DoubleHyphen), previousSymbols.ElementAt(orderIndex++));
|
||||
Assert.Equal(new HtmlSymbol("fvd", HtmlSymbolType.Text), previousSymbols.ElementAt(orderIndex++));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LookaheadUntil_ReturnsFalseAfterIteratingOverAllSymbolsIfConditionIsNotMet()
|
||||
{
|
||||
// Arrange
|
||||
var tokenizer = CreateContentTokenizer("asdf--fvd");
|
||||
|
||||
// Act
|
||||
var symbols = new Stack<HtmlSymbol>();
|
||||
var symbolFound = tokenizer.LookaheadUntil((s, p) =>
|
||||
{
|
||||
symbols.Push(s);
|
||||
return false;
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.False(symbolFound);
|
||||
Assert.Equal(3, symbols.Count);
|
||||
Assert.Equal(new HtmlSymbol("fvd", HtmlSymbolType.Text), symbols.Pop());
|
||||
Assert.Equal(new HtmlSymbol("--", HtmlSymbolType.DoubleHyphen), symbols.Pop());
|
||||
Assert.Equal(new HtmlSymbol("asdf", HtmlSymbolType.Text), symbols.Pop());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LookaheadUntil_ReturnsTrueAndBreaksIteration()
|
||||
{
|
||||
// Arrange
|
||||
var tokenizer = CreateContentTokenizer("asdf--fvd");
|
||||
|
||||
// Act
|
||||
var symbols = new Stack<HtmlSymbol>();
|
||||
var symbolFound = tokenizer.LookaheadUntil((s, p) =>
|
||||
{
|
||||
symbols.Push(s);
|
||||
return s.Type == HtmlSymbolType.DoubleHyphen;
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.True(symbolFound);
|
||||
Assert.Equal(2, symbols.Count);
|
||||
Assert.Equal(new HtmlSymbol("--", HtmlSymbolType.DoubleHyphen), symbols.Pop());
|
||||
Assert.Equal(new HtmlSymbol("asdf", HtmlSymbolType.Text), symbols.Pop());
|
||||
}
|
||||
|
||||
private static TestTokenizerBackedParser CreateContentTokenizer(string content)
|
||||
{
|
||||
var source = TestRazorSourceDocument.Create(content);
|
||||
var options = RazorParserOptions.CreateDefault();
|
||||
var context = new ParserContext(source, options);
|
||||
|
||||
var tokenizer = new TestTokenizerBackedParser(HtmlLanguageCharacteristics.Instance, context);
|
||||
return tokenizer;
|
||||
}
|
||||
|
||||
private class ExposedTokenizer : Tokenizer<CSharpSymbol, CSharpSymbolType>
|
||||
{
|
||||
public ExposedTokenizer(string input)
|
||||
|
|
@ -116,5 +195,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class TestTokenizerBackedParser : TokenizerBackedParser<HtmlTokenizer, HtmlSymbol, HtmlSymbolType>
|
||||
{
|
||||
internal TestTokenizerBackedParser(LanguageCharacteristics<HtmlTokenizer, HtmlSymbol, HtmlSymbolType> language, ParserContext context) : base(language, context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ParseBlock()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override bool SymbolTypeEquals(HtmlSymbolType x, HtmlSymbolType y)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal new bool LookaheadUntil(Func<HtmlSymbol, IEnumerable<HtmlSymbol>, bool> condition)
|
||||
{
|
||||
return base.LookaheadUntil(condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
// Assert
|
||||
Assert.True(context.AllowMinimizedBooleanTagHelperAttributes);
|
||||
Assert.True(context.AllowHtmlCommentsInTagHelpers);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -26,6 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
// Assert
|
||||
Assert.False(context.AllowMinimizedBooleanTagHelperAttributes);
|
||||
Assert.False(context.AllowHtmlCommentsInTagHelpers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Test
|
||||
{
|
||||
public class TagHelperParseTreeRewriterTests
|
||||
{
|
||||
public void IsComment_ReturnsTrueForSpanInHtmlCommentBlock()
|
||||
{
|
||||
// Arrange
|
||||
SpanFactory spanFactory = new SpanFactory();
|
||||
|
||||
Span content = spanFactory.Markup("<!-- comment -->");
|
||||
Block commentBlock = new HtmlCommentBlock(content);
|
||||
|
||||
// Act
|
||||
bool actualResult = TagHelperParseTreeRewriter.IsComment(content);
|
||||
|
||||
// Assert
|
||||
Assert.True(actualResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,10 @@ Document -
|
|||
IntermediateToken - - CSharp - #pragma warning restore 0414
|
||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Double.cshtml)
|
||||
IntermediateToken - (0:0,0 [12] HtmlCommentWithQuote_Double.cshtml) - Html - <!-- " -->\n
|
||||
IntermediateToken - (0:0,0 [4] HtmlCommentWithQuote_Double.cshtml) - Html - <!--
|
||||
IntermediateToken - (4:0,4 [3] HtmlCommentWithQuote_Double.cshtml) - Html - "
|
||||
IntermediateToken - (7:0,7 [3] HtmlCommentWithQuote_Double.cshtml) - Html - -->
|
||||
IntermediateToken - (10:0,10 [2] HtmlCommentWithQuote_Double.cshtml) - Html - \n
|
||||
IntermediateToken - (12:1,0 [4] HtmlCommentWithQuote_Double.cshtml) - Html - <img
|
||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Double.cshtml) - Html - src="~/images/submit.png"
|
||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Double.cshtml) - Html - />
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ Document -
|
|||
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_HtmlCommentWithQuote_Double_Runtime - -
|
||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Double.cshtml)
|
||||
IntermediateToken - (0:0,0 [12] HtmlCommentWithQuote_Double.cshtml) - Html - <!-- " -->\n
|
||||
IntermediateToken - (0:0,0 [4] HtmlCommentWithQuote_Double.cshtml) - Html - <!--
|
||||
IntermediateToken - (4:0,4 [3] HtmlCommentWithQuote_Double.cshtml) - Html - "
|
||||
IntermediateToken - (7:0,7 [3] HtmlCommentWithQuote_Double.cshtml) - Html - -->
|
||||
IntermediateToken - (10:0,10 [2] HtmlCommentWithQuote_Double.cshtml) - Html - \n
|
||||
IntermediateToken - (12:1,0 [4] HtmlCommentWithQuote_Double.cshtml) - Html - <img
|
||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Double.cshtml) - Html - src="~/images/submit.png"
|
||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Double.cshtml) - Html - />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ Document -
|
|||
IntermediateToken - - CSharp - #pragma warning restore 0414
|
||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Single.cshtml)
|
||||
IntermediateToken - (0:0,0 [12] HtmlCommentWithQuote_Single.cshtml) - Html - <!-- ' -->\n
|
||||
IntermediateToken - (0:0,0 [4] HtmlCommentWithQuote_Single.cshtml) - Html - <!--
|
||||
IntermediateToken - (4:0,4 [3] HtmlCommentWithQuote_Single.cshtml) - Html - '
|
||||
IntermediateToken - (7:0,7 [3] HtmlCommentWithQuote_Single.cshtml) - Html - -->
|
||||
IntermediateToken - (10:0,10 [2] HtmlCommentWithQuote_Single.cshtml) - Html - \n
|
||||
IntermediateToken - (12:1,0 [4] HtmlCommentWithQuote_Single.cshtml) - Html - <img
|
||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Single.cshtml) - Html - src="~/images/submit.png"
|
||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Single.cshtml) - Html - />
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ Document -
|
|||
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_HtmlCommentWithQuote_Single_Runtime - -
|
||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Single.cshtml)
|
||||
IntermediateToken - (0:0,0 [12] HtmlCommentWithQuote_Single.cshtml) - Html - <!-- ' -->\n
|
||||
IntermediateToken - (0:0,0 [4] HtmlCommentWithQuote_Single.cshtml) - Html - <!--
|
||||
IntermediateToken - (4:0,4 [3] HtmlCommentWithQuote_Single.cshtml) - Html - '
|
||||
IntermediateToken - (7:0,7 [3] HtmlCommentWithQuote_Single.cshtml) - Html - -->
|
||||
IntermediateToken - (10:0,10 [2] HtmlCommentWithQuote_Single.cshtml) - Html - \n
|
||||
IntermediateToken - (12:1,0 [4] HtmlCommentWithQuote_Single.cshtml) - Html - <img
|
||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Single.cshtml) - Html - src="~/images/submit.png"
|
||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Single.cshtml) - Html - />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
|
|
@ -55,6 +56,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
);
|
||||
}
|
||||
|
||||
public HtmlCommentBlock HtmlCommentBlock(string content)
|
||||
{
|
||||
return HtmlCommentBlock(_factory, f => new SyntaxTreeNode[] { f.Markup(content).Accepts(AcceptedCharactersInternal.WhiteSpace) });
|
||||
}
|
||||
|
||||
public static HtmlCommentBlock HtmlCommentBlock(SpanFactory factory, Func<SpanFactory, IEnumerable<SyntaxTreeNode>> nodesBuilder = null)
|
||||
{
|
||||
var nodes = new List<SyntaxTreeNode>();
|
||||
nodes.Add(factory.Markup("<!--").Accepts(AcceptedCharactersInternal.None));
|
||||
if (nodesBuilder != null)
|
||||
{
|
||||
nodes.AddRange(nodesBuilder(factory));
|
||||
}
|
||||
nodes.Add(factory.Markup("-->").Accepts(AcceptedCharactersInternal.None));
|
||||
|
||||
return new HtmlCommentBlock(nodes.ToArray());
|
||||
}
|
||||
|
||||
public Block TagHelperBlock(
|
||||
string tagName,
|
||||
TagMode tagMode,
|
||||
|
|
|
|||
|
|
@ -217,4 +217,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal class HtmlCommentBlock : Block
|
||||
{
|
||||
private const BlockKindInternal ThisBlockKind = BlockKindInternal.HtmlComment;
|
||||
|
||||
public HtmlCommentBlock(params SyntaxTreeNode[] children)
|
||||
: base(ThisBlockKind, children, ParentChunkGenerator.Null)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue