Revert "Revert "Make Razor HTML Comments aware (#2178)""
This reverts commit 1f3f4b79da.
This commit is contained in:
parent
1f3f4b79da
commit
c874f84c3d
|
|
@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
Comment = 8,
|
Comment = 8,
|
||||||
Tag = 9
|
Tag = 9,
|
||||||
|
HtmlComment = 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,6 +12,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
private const string ScriptTagName = "script";
|
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 static readonly char[] ValidAfterTypeAttributeNameCharacters = { ' ', '\t', '\r', '\n', '\f', '=' };
|
||||||
private SourceLocation _lastTagStart = SourceLocation.Zero;
|
private SourceLocation _lastTagStart = SourceLocation.Zero;
|
||||||
private HtmlSymbol _bufferedOpenAngle;
|
private HtmlSymbol _bufferedOpenAngle;
|
||||||
|
|
@ -492,33 +495,37 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
if (AcceptAndMoveNext())
|
if (AcceptAndMoveNext())
|
||||||
{
|
{
|
||||||
if (CurrentSymbol.Type == HtmlSymbolType.DoubleHyphen)
|
if (IsHtmlCommentAhead())
|
||||||
{
|
{
|
||||||
AcceptAndMoveNext();
|
using (Context.Builder.StartBlock(BlockKindInternal.HtmlComment))
|
||||||
|
|
||||||
Span.EditHandler.AcceptedCharacters = AcceptedCharactersInternal.Any;
|
|
||||||
while (!EndOfFile)
|
|
||||||
{
|
{
|
||||||
SkipToAndParseCode(HtmlSymbolType.DoubleHyphen);
|
// Accept the double-hyphen symbol at the beginning of the comment block.
|
||||||
if (At(HtmlSymbolType.DoubleHyphen))
|
AcceptAndMoveNext();
|
||||||
{
|
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.None);
|
||||||
AcceptWhile(HtmlSymbolType.DoubleHyphen);
|
|
||||||
|
|
||||||
if (At(HtmlSymbolType.Text) &&
|
Span.EditHandler.AcceptedCharacters = AcceptedCharactersInternal.WhiteSpace;
|
||||||
string.Equals(CurrentSymbol.Content, "-", StringComparison.Ordinal))
|
while (!EndOfFile)
|
||||||
{
|
{
|
||||||
AcceptAndMoveNext();
|
SkipToAndParseCode(HtmlSymbolType.DoubleHyphen);
|
||||||
}
|
var lastDoubleHyphen = AcceptAllButLastDoubleHyphens();
|
||||||
|
|
||||||
if (At(HtmlSymbolType.CloseAngle))
|
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();
|
AcceptAndMoveNext();
|
||||||
|
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.None);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (lastDoubleHyphen != null)
|
||||||
|
{
|
||||||
|
Accept(lastDoubleHyphen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
else if (CurrentSymbol.Type == HtmlSymbolType.LeftBracket)
|
else if (CurrentSymbol.Type == HtmlSymbolType.LeftBracket)
|
||||||
{
|
{
|
||||||
|
|
@ -537,6 +544,138 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return false;
|
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()
|
private bool CData()
|
||||||
{
|
{
|
||||||
if (CurrentSymbol.Type == HtmlSymbolType.Text && string.Equals(CurrentSymbol.Content, "cdata", StringComparison.OrdinalIgnoreCase))
|
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[, <!--.
|
// Checking to see if we meet the conditions of a special '!' tag: <!DOCTYPE, <![CDATA[, <!--.
|
||||||
if (!IsBangEscape(lookahead: 1))
|
if (!IsBangEscape(lookahead: 1))
|
||||||
{
|
{
|
||||||
|
if (Lookahead(2)?.Type == HtmlSymbolType.DoubleHyphen)
|
||||||
|
{
|
||||||
|
Output(SpanKindInternal.Markup);
|
||||||
|
}
|
||||||
|
|
||||||
AcceptAndMoveNext(); // Accept '<'
|
AcceptAndMoveNext(); // Accept '<'
|
||||||
BangTag();
|
BangTag();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1761,4 +1906,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,6 +8,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
internal class HtmlSymbol : SymbolBase<HtmlSymbolType>
|
internal class HtmlSymbol : SymbolBase<HtmlSymbolType>
|
||||||
{
|
{
|
||||||
|
internal static readonly HtmlSymbol Hyphen = new HtmlSymbol("-", HtmlSymbolType.Text);
|
||||||
|
|
||||||
public HtmlSymbol(string content, HtmlSymbolType type)
|
public HtmlSymbol(string content, HtmlSymbolType type)
|
||||||
: base(content, type, RazorDiagnostic.EmptyArray)
|
: base(content, type, RazorDiagnostic.EmptyArray)
|
||||||
{
|
{
|
||||||
|
|
@ -29,4 +31,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -490,20 +490,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
if (HasAllowedChildren())
|
if (HasAllowedChildren())
|
||||||
{
|
{
|
||||||
var content = child.Content;
|
var isDisallowedContent = true;
|
||||||
if (!string.IsNullOrWhiteSpace(content))
|
if (_featureFlags.AllowHtmlCommentsInTagHelpers)
|
||||||
{
|
{
|
||||||
var trimmedStart = content.TrimStart();
|
isDisallowedContent = !IsComment(child) && child.Kind != SpanKindInternal.Transition && child.Kind != SpanKindInternal.Code;
|
||||||
var whitespace = content.Substring(0, content.Length - trimmedStart.Length);
|
}
|
||||||
var errorStart = SourceLocationTracker.Advance(child.Start, whitespace);
|
|
||||||
var length = trimmedStart.TrimEnd().Length;
|
if (isDisallowedContent)
|
||||||
var allowedChildren = _currentTagHelperTracker.AllowedChildren;
|
{
|
||||||
var allowedChildrenString = string.Join(", ", allowedChildren);
|
var content = child.Content;
|
||||||
errorSink.OnError(
|
if (!string.IsNullOrWhiteSpace(content))
|
||||||
RazorDiagnosticFactory.CreateTagHelper_CannotHaveNonTagContent(
|
{
|
||||||
new SourceSpan(errorStart, length),
|
var trimmedStart = content.TrimStart();
|
||||||
_currentTagHelperTracker.TagName,
|
var whitespace = content.Substring(0, content.Length - trimmedStart.Length);
|
||||||
allowedChildrenString));
|
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;
|
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)
|
private static void EnsureTagBlock(Block tagBlock)
|
||||||
{
|
{
|
||||||
Debug.Assert(tagBlock.Type == BlockKindInternal.Tag);
|
Debug.Assert(tagBlock.Type == BlockKindInternal.Tag);
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,52 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return symbols[count];
|
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()
|
protected internal bool NextToken()
|
||||||
{
|
{
|
||||||
PreviousSymbol = CurrentSymbol;
|
PreviousSymbol = CurrentSymbol;
|
||||||
|
|
@ -254,12 +300,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
protected internal bool NextIs(Func<TSymbol, bool> condition)
|
protected internal bool NextIs(Func<TSymbol, bool> condition)
|
||||||
{
|
{
|
||||||
var cur = CurrentSymbol;
|
var cur = CurrentSymbol;
|
||||||
NextToken();
|
if (NextToken())
|
||||||
var result = condition(CurrentSymbol);
|
{
|
||||||
PutCurrentBack();
|
var result = condition(CurrentSymbol);
|
||||||
PutBack(cur);
|
PutCurrentBack();
|
||||||
EnsureCurrent();
|
PutBack(cur);
|
||||||
return result;
|
EnsureCurrent();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PutBack(cur);
|
||||||
|
EnsureCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal bool Was(TSymbolType type)
|
protected internal bool Was(TSymbolType type)
|
||||||
|
|
@ -621,4 +676,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Initialize(Span);
|
Initialize(Span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,26 +8,33 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
public static RazorParserFeatureFlags Create(RazorLanguageVersion version)
|
public static RazorParserFeatureFlags Create(RazorLanguageVersion version)
|
||||||
{
|
{
|
||||||
var allowMinimizedBooleanTagHelperAttributes = false;
|
var allowMinimizedBooleanTagHelperAttributes = false;
|
||||||
|
var allowHtmlCommentsInTagHelpers = false;
|
||||||
|
|
||||||
if (version.CompareTo(RazorLanguageVersion.Version_2_1) >= 0)
|
if (version.CompareTo(RazorLanguageVersion.Version_2_1) >= 0)
|
||||||
{
|
{
|
||||||
// Added in 2.1
|
// Added in 2.1
|
||||||
allowMinimizedBooleanTagHelperAttributes = true;
|
allowMinimizedBooleanTagHelperAttributes = true;
|
||||||
|
allowHtmlCommentsInTagHelpers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DefaultRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes);
|
return new DefaultRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes, allowHtmlCommentsInTagHelpers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
public abstract bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||||
|
|
||||||
|
public abstract bool AllowHtmlCommentsInTagHelpers { get; }
|
||||||
|
|
||||||
private class DefaultRazorParserFeatureFlags : RazorParserFeatureFlags
|
private class DefaultRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||||
{
|
{
|
||||||
public DefaultRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes)
|
public DefaultRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelpers)
|
||||||
{
|
{
|
||||||
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||||
|
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelpers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||||
|
|
||||||
|
public override bool AllowHtmlCommentsInTagHelpers { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,6 +19,8 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
Comment,
|
Comment,
|
||||||
Tag
|
Tag,
|
||||||
|
|
||||||
|
HtmlComment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +367,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
ParseDocumentTest(
|
ParseDocumentTest(
|
||||||
"@section foo "
|
"@section foo "
|
||||||
+ Environment.NewLine
|
+ Environment.NewLine
|
||||||
+ Environment.NewLine
|
+ 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.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
|
||||||
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
|
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
Factory.Markup("<!-- -->")),
|
BlockFactory.HtmlCommentBlock(" "),
|
||||||
|
Factory.EmptyHtml()),
|
||||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||||
Factory.EmptyHtml()));
|
Factory.EmptyHtml()));
|
||||||
}
|
}
|
||||||
|
|
@ -630,7 +631,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
|
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
|
||||||
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
|
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
Factory.Markup("<!-- > \" '-->")),
|
BlockFactory.HtmlCommentBlock(" > \" '"),
|
||||||
|
Factory.EmptyHtml()),
|
||||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||||
Factory.EmptyHtml()));
|
Factory.EmptyHtml()));
|
||||||
}
|
}
|
||||||
|
|
@ -655,7 +657,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.Markup(Environment.NewLine),
|
Factory.Markup(Environment.NewLine),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
Factory.Markup("<a" + Environment.NewLine)),
|
Factory.Markup("<a" + Environment.NewLine)),
|
||||||
Factory.Markup("<!-- > \" '-->")),
|
BlockFactory.HtmlCommentBlock(" > \" '"),
|
||||||
|
Factory.EmptyHtml()),
|
||||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||||
Factory.EmptyHtml()));
|
Factory.EmptyHtml()));
|
||||||
}
|
}
|
||||||
|
|
@ -760,4 +763,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
ParseDocumentTest(input, new[] { SectionDirective.Directive }, (Block)expected);
|
ParseDocumentTest(input, new[] { SectionDirective.Directive }, (Block)expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.Code(Environment.NewLine).AsStatement().AutoCompleteWith(null),
|
Factory.Code(Environment.NewLine).AsStatement().AutoCompleteWith(null),
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
Factory.Markup(" "),
|
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.Markup(Environment.NewLine).Accepts(AcceptedCharactersInternal.None)),
|
||||||
Factory.EmptyCSharp().AsStatement(),
|
Factory.EmptyCSharp().AsStatement(),
|
||||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||||
|
|
@ -333,7 +333,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ParseBlockSupportsCommentAsBlock()
|
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]
|
[Fact]
|
||||||
|
|
@ -344,8 +350,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
||||||
Factory.Markup("bar"),
|
Factory.Markup("bar"),
|
||||||
Factory.Markup("<!-- zoop -->").Accepts(AcceptedCharactersInternal.None),
|
BlockFactory.HtmlCommentBlock(" zoop "),
|
||||||
Factory.Markup("baz"),
|
Factory.Markup("baz").Accepts(AcceptedCharactersInternal.None),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +361,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var factory = new SpanFactory();
|
var factory = new SpanFactory();
|
||||||
|
var blockFactory = new BlockFactory(factory);
|
||||||
return new TheoryData<string, MarkupBlock>
|
return new TheoryData<string, MarkupBlock>
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
@ -363,7 +369,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||||
factory.Markup("<!--- Hello World --->").Accepts(AcceptedCharactersInternal.None),
|
blockFactory.HtmlCommentBlock("- Hello World -"),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||||
},
|
},
|
||||||
|
|
@ -372,7 +378,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||||
factory.Markup("<!---- Hello World ---->").Accepts(AcceptedCharactersInternal.None),
|
blockFactory.HtmlCommentBlock("-- Hello World --"),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||||
},
|
},
|
||||||
|
|
@ -381,7 +387,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||||
factory.Markup("<!----- Hello World ----->").Accepts(AcceptedCharactersInternal.None),
|
blockFactory.HtmlCommentBlock("--- Hello World ---"),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||||
},
|
},
|
||||||
|
|
@ -390,7 +396,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
factory.Markup("<div>").Accepts(AcceptedCharactersInternal.None)),
|
||||||
factory.Markup("<!----- Hello < --- > World </div> ----->").Accepts(AcceptedCharactersInternal.None),
|
blockFactory.HtmlCommentBlock("--- Hello < --- > World </div> ---"),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
factory.Markup("</div>").Accepts(AcceptedCharactersInternal.None)))
|
||||||
},
|
},
|
||||||
|
|
@ -410,19 +416,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ParseBlockProperlyBalancesCommentStartAndEndTags()
|
public void ParseBlockProperlyBalancesCommentStartAndEndTags()
|
||||||
{
|
{
|
||||||
SingleSpanBlockTest("<!--<foo></bar>-->", BlockKindInternal.Markup, SpanKindInternal.Markup, acceptedCharacters: AcceptedCharactersInternal.None);
|
ParseBlockTest("<!--<foo></bar>-->", new MarkupBlock(BlockFactory.HtmlCommentBlock("<foo></bar>")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ParseBlockTerminatesAtEOFWhenParsingComment()
|
public void ParseBlockTerminatesAtEOFWhenParsingComment()
|
||||||
{
|
{
|
||||||
SingleSpanBlockTest("<!--<foo>", "<!--<foo>", BlockKindInternal.Markup, SpanKindInternal.Markup);
|
ParseBlockTest(
|
||||||
|
"<!--<foo>",
|
||||||
|
new MarkupBlock(
|
||||||
|
Factory.Markup("<!--<foo>").Accepts(AcceptedCharactersInternal.None)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ParseBlockOnlyTerminatesCommentOnFullEndSequence()
|
public void ParseBlockOnlyTerminatesCommentOnFullEndSequence()
|
||||||
{
|
{
|
||||||
SingleSpanBlockTest("<!--<foo>--</bar>-->", BlockKindInternal.Markup, SpanKindInternal.Markup, acceptedCharacters: AcceptedCharactersInternal.None);
|
ParseBlockTest("<!--<foo>--</bar>-->", new MarkupBlock(BlockFactory.HtmlCommentBlock("<foo>--</bar>")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -432,8 +441,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
||||||
Factory.Markup("<!--<foo></bar-->").Accepts(AcceptedCharactersInternal.None),
|
BlockFactory.HtmlCommentBlock("<foo></bar"),
|
||||||
Factory.Markup("-->"),
|
Factory.Markup("-->").Accepts(AcceptedCharactersInternal.None),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
||||||
}
|
}
|
||||||
|
|
@ -645,4 +654,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.Markup("</script>").Accepts(AcceptedCharactersInternal.None))));
|
Factory.Markup("</script>").Accepts(AcceptedCharactersInternal.None))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +214,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ParseDocumentReturnsOneMarkupSegmentIfNoCodeBlocksEncountered()
|
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]
|
[Fact]
|
||||||
|
|
@ -795,4 +800,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
ParseDocumentTest("<span foo='@ @' />", expected, expectedErrors);
|
ParseDocumentTest("<span foo='@ @' />", expected, expectedErrors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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",
|
ParseBlockTest("<!--Foo--> Bar",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
Factory.Markup("<!--Foo-->").Accepts(AcceptedCharactersInternal.None),
|
BlockFactory.HtmlCommentBlock("Foo"),
|
||||||
Factory.Markup(" ").Accepts(AcceptedCharactersInternal.None)));
|
Factory.Markup(" ").Accepts(AcceptedCharactersInternal.None)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,4 +203,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
BlockFactory.MarkupTagBlock("</" + tagName)));
|
BlockFactory.MarkupTagBlock("</" + tagName)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,13 +112,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
Factory.Markup("<foo>").Accepts(AcceptedCharactersInternal.None)),
|
||||||
Factory.Markup("<!-- "),
|
BlockFactory.HtmlCommentBlock(Factory, f => new SyntaxTreeNode[] {
|
||||||
new ExpressionBlock(
|
f.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace),
|
||||||
Factory.CodeTransition(),
|
new ExpressionBlock(
|
||||||
Factory.Code("foo")
|
f.CodeTransition(),
|
||||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
f.Code("foo")
|
||||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
Factory.Markup(" -->").Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||||
|
f.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace) }),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
Factory.Markup("</foo>").Accepts(AcceptedCharactersInternal.None))));
|
||||||
}
|
}
|
||||||
|
|
@ -451,4 +452,4 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.EmptyHtml()));
|
Factory.EmptyHtml()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2950,7 +2950,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
intType),
|
intType),
|
||||||
RazorDiagnosticFactory.CreateParsing_TagHelperIndexerAttributeNameMustIncludeKey(
|
RazorDiagnosticFactory.CreateParsing_TagHelperIndexerAttributeNameMustIncludeKey(
|
||||||
new SourceSpan(7, 0, 7, 11),
|
new SourceSpan(7, 0, 7, 11),
|
||||||
"int-prefix-",
|
"int-prefix-",
|
||||||
"input"),
|
"input"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -2973,7 +2973,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
stringType),
|
stringType),
|
||||||
RazorDiagnosticFactory.CreateParsing_TagHelperIndexerAttributeNameMustIncludeKey(
|
RazorDiagnosticFactory.CreateParsing_TagHelperIndexerAttributeNameMustIncludeKey(
|
||||||
new SourceSpan(7, 0, 7, 14),
|
new SourceSpan(7, 0, 7, 14),
|
||||||
"string-prefix-",
|
"string-prefix-",
|
||||||
"input"),
|
"input"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -3638,7 +3638,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
RazorDiagnosticFactory.CreateTagHelper_EmptyBoundAttribute(
|
RazorDiagnosticFactory.CreateTagHelper_EmptyBoundAttribute(
|
||||||
new SourceSpan(7, 0, 7, 21),
|
new SourceSpan(7, 0, 7, 21),
|
||||||
"bound-required-string",
|
"bound-required-string",
|
||||||
"input",
|
"input",
|
||||||
stringType),
|
stringType),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -3962,7 +3962,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.Build(),
|
.Build(),
|
||||||
};
|
};
|
||||||
|
|
||||||
var featureFlags = new TestRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes: false);
|
var featureFlags = new TestRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes: false, allowHtmlCommentsInTagHelper: false);
|
||||||
|
|
||||||
var expectedOutput = new MarkupBlock(
|
var expectedOutput = new MarkupBlock(
|
||||||
new MarkupTagHelperBlock(
|
new MarkupTagHelperBlock(
|
||||||
|
|
@ -3994,12 +3994,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
private class TestRazorParserFeatureFlags : RazorParserFeatureFlags
|
private class TestRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||||
{
|
{
|
||||||
public TestRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes)
|
public TestRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelper)
|
||||||
{
|
{
|
||||||
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||||
|
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||||
|
|
||||||
|
public override bool AllowHtmlCommentsInTagHelpers { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -254,7 +254,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("input")
|
.RequireTagName("input")
|
||||||
.RequireTagStructure(TagStructure.WithoutEndTag))
|
.RequireTagStructure(TagStructure.WithoutEndTag))
|
||||||
|
|
@ -371,7 +371,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
|
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
|
||||||
.Build(),
|
.Build(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
EvaluateData(
|
EvaluateData(
|
||||||
descriptors,
|
descriptors,
|
||||||
|
|
@ -793,7 +793,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("StrongTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("StrongTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("strong")
|
.RequireTagName("strong")
|
||||||
.RequireAttributeDescriptor(attribute => attribute.Name("required")))
|
.RequireAttributeDescriptor(attribute => attribute.Name("required")))
|
||||||
|
|
@ -830,7 +830,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
|
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
|
||||||
.Build(),
|
.Build(),
|
||||||
TagHelperDescriptorBuilder.Create("BRTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("BRTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("br")
|
.RequireTagName("br")
|
||||||
.RequireTagStructure(TagStructure.WithoutEndTag))
|
.RequireTagStructure(TagStructure.WithoutEndTag))
|
||||||
|
|
@ -1108,6 +1108,243 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
EvaluateData(descriptors, documentContent, (MarkupBlock)expectedOutput, (RazorDiagnostic[])expectedErrors);
|
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]
|
[Fact]
|
||||||
public void Rewrite_UnderstandsNullTagNameWithAllowedChildrenForCatchAll()
|
public void Rewrite_UnderstandsNullTagNameWithAllowedChildrenForCatchAll()
|
||||||
{
|
{
|
||||||
|
|
@ -1173,7 +1410,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("input")
|
.RequireTagName("input")
|
||||||
.RequireTagStructure(TagStructure.WithoutEndTag))
|
.RequireTagStructure(TagStructure.WithoutEndTag))
|
||||||
|
|
@ -1646,7 +1883,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("pTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("pTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("p")
|
.RequireTagName("p")
|
||||||
.RequireAttributeDescriptor(attribute => attribute.Name("class")))
|
.RequireAttributeDescriptor(attribute => attribute.Name("class")))
|
||||||
|
|
@ -3901,14 +4138,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var factory = new SpanFactory();
|
var factory = new SpanFactory();
|
||||||
|
var blockFactory = new BlockFactory(factory);
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
"<foo><!-- Hello World --></foo>",
|
"<foo><!-- Hello World --></foo>",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("<foo>")),
|
factory.Markup("<foo>")),
|
||||||
factory.Markup("<!-- Hello World -->"),
|
blockFactory.HtmlCommentBlock (" Hello World "),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("</foo>")))
|
factory.Markup("</foo>")))
|
||||||
};
|
};
|
||||||
|
|
@ -3918,13 +4155,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("<foo>")),
|
factory.Markup("<foo>")),
|
||||||
factory.Markup("<!-- "),
|
BlockFactory.HtmlCommentBlock(factory, f=> new SyntaxTreeNode[]{
|
||||||
new ExpressionBlock(
|
f.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace),
|
||||||
factory.CodeTransition(),
|
new ExpressionBlock(
|
||||||
factory.Code("foo")
|
f.CodeTransition(),
|
||||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
f.Code("foo")
|
||||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
factory.Markup(" -->"),
|
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||||
|
factory.Markup(" ").Accepts(AcceptedCharactersInternal.WhiteSpace) }),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("</foo>")))
|
factory.Markup("</foo>")))
|
||||||
};
|
};
|
||||||
|
|
@ -4000,8 +4238,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition(),
|
||||||
factory.Code("foo")
|
factory.Code("foo")
|
||||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
|
||||||
factory.Markup(" ]]>"),
|
factory.Markup(" ]]>"),
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
factory.Markup("</foo>")))
|
factory.Markup("</foo>")))
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -56,6 +56,85 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Assert.Equal("pre-existing values", tokenizer.Buffer.ToString(), StringComparer.Ordinal);
|
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>
|
private class ExposedTokenizer : Tokenizer<CSharpSymbol, CSharpSymbolType>
|
||||||
{
|
{
|
||||||
public ExposedTokenizer(string input)
|
public ExposedTokenizer(string input)
|
||||||
|
|
@ -116,5 +195,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
throw new NotImplementedException();
|
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
|
||||||
Assert.True(context.AllowMinimizedBooleanTagHelperAttributes);
|
Assert.True(context.AllowMinimizedBooleanTagHelperAttributes);
|
||||||
|
Assert.True(context.AllowHtmlCommentsInTagHelpers);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -26,6 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(context.AllowMinimizedBooleanTagHelperAttributes);
|
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
|
IntermediateToken - - CSharp - #pragma warning restore 0414
|
||||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Double.cshtml)
|
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 - (12:1,0 [4] HtmlCommentWithQuote_Double.cshtml) - Html - <img
|
||||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Double.cshtml) - Html - src="~/images/submit.png"
|
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Double.cshtml) - Html - src="~/images/submit.png"
|
||||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Double.cshtml) - Html - />
|
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Double.cshtml) - Html - />
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ Document -
|
||||||
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_HtmlCommentWithQuote_Double_Runtime - -
|
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_HtmlCommentWithQuote_Double_Runtime - -
|
||||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Double.cshtml)
|
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 - (12:1,0 [4] HtmlCommentWithQuote_Double.cshtml) - Html - <img
|
||||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Double.cshtml) - Html - src="~/images/submit.png"
|
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Double.cshtml) - Html - src="~/images/submit.png"
|
||||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Double.cshtml) - Html - />
|
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Double.cshtml) - Html - />
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@ Document -
|
||||||
IntermediateToken - - CSharp - #pragma warning restore 0414
|
IntermediateToken - - CSharp - #pragma warning restore 0414
|
||||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Single.cshtml)
|
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 - (12:1,0 [4] HtmlCommentWithQuote_Single.cshtml) - Html - <img
|
||||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Single.cshtml) - Html - src="~/images/submit.png"
|
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Single.cshtml) - Html - src="~/images/submit.png"
|
||||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Single.cshtml) - Html - />
|
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Single.cshtml) - Html - />
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ Document -
|
||||||
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_HtmlCommentWithQuote_Single_Runtime - -
|
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_HtmlCommentWithQuote_Single_Runtime - -
|
||||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||||
HtmlContent - (0:0,0 [45] HtmlCommentWithQuote_Single.cshtml)
|
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 - (12:1,0 [4] HtmlCommentWithQuote_Single.cshtml) - Html - <img
|
||||||
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Single.cshtml) - Html - src="~/images/submit.png"
|
IntermediateToken - (16:1,4 [26] HtmlCommentWithQuote_Single.cshtml) - Html - src="~/images/submit.png"
|
||||||
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Single.cshtml) - Html - />
|
IntermediateToken - (42:1,30 [3] HtmlCommentWithQuote_Single.cshtml) - Html - />
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
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(
|
public Block TagHelperBlock(
|
||||||
string tagName,
|
string tagName,
|
||||||
TagMode tagMode,
|
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