// "+++ <name>" with optional trailing whitespace internal virtual bool IsOpeningLine(BlockProcessor blockProcessor) { StringSlice line = blockProcessor.Line; if (line.NextChar() != '+' || line.NextChar() != '+' || line.NextChar() != ' ') { return(false); } for (int i = 0; i < _nameLength; i++) { if (line.NextChar() != _name[i]) { return(false); } } // Nothing other than whitespace after the name. A multipart block's name may begin with the name of another // multipart block, this ensures we don't confuse such blocks. line.NextChar(); line.TrimEnd(); return(line.CurrentChar == '\0'); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { if (slice.CurrentChar == '$' && slice.PeekChar(1) == '(') { slice.NextChar(); slice.NextChar(); int start = slice.Start; int end = start; while (slice.CurrentChar != ')') { end = slice.Start; slice.NextChar(); } processor.GetSourcePosition(slice.Start, out int line, out int column); processor.Inline = new VariableInline { Line = line, Column = column, VariableName = new StringSlice(slice.Text, start, end) }; slice.NextChar(); return(true); } return(false); }
private static bool MatchPath(ref StringSlice slice, ref string path) { if (slice.CurrentChar != '(') { return(false); } slice.NextChar(); SkipWhitespace(ref slice); string includedFilePath; if (slice.CurrentChar == '<') { includedFilePath = TryGetStringBeforeChars(new char[] { ')', '>' }, ref slice, breakOnWhitespace: true); } else { includedFilePath = TryGetStringBeforeChars(new char[] { ')' }, ref slice, breakOnWhitespace: true); }; if (includedFilePath == null) { return(false); } if (includedFilePath.Length >= 1 && includedFilePath.First() == '<' && slice.CurrentChar == '>') { includedFilePath = includedFilePath.Substring(1, includedFilePath.Length - 1).Trim(); } if (slice.CurrentChar == ')') { path = includedFilePath; slice.NextChar(); return(true); } else { var title = TryGetStringBeforeChars(new char[] { ')' }, ref slice, breakOnWhitespace: false); if (title == null) { return(false); } else { if (title.Length >= 2 && title.First() == '\'' && title.Last() == '\'') { title = title.Substring(1, title.Length - 2).Trim(); } else if (title.Length >= 2 && title.First() == '\"' && title.Last() == '\"') { title = title.Substring(1, title.Length - 2).Trim(); } path = includedFilePath; slice.NextChar(); return(true); } } }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // A tasklist is either // [ ] // or [x] or [X] if (!(processor.Block !.Parent is ListItemBlock listItemBlock)) { return(false); } var startingPosition = slice.Start; var c = slice.NextChar(); if (!c.IsSpace() && c != 'x' && c != 'X') { return(false); } if (slice.NextChar() != ']') { return(false); } // Skip last ] slice.SkipChar(); // Create the TaskList var taskItem = new TaskList() { Span = { Start = processor.GetSourcePosition(startingPosition, out int line, out int column) },
private bool MatchBookMarkQuery(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet) { if (slice.CurrentChar != '#') { return(false); } var queryChar = slice.CurrentChar; var query = StringBuilderCache.Local(); var c = slice.NextChar(); while (c != '\0' && c != '"' && c != ')') { query.Append(c); c = slice.NextChar(); } var queryString = query.ToString().Trim(); CodeRange codeRange; if (TryGetLineRange(queryString, out codeRange)) { codeSnippet.BookMarkRange = codeRange; } else { codeSnippet.TagName = queryString; } return(true); }
private bool MatchTitle(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet) { if (slice.CurrentChar != '"') { return(false); } var title = StringBuilderCache.Local(); var c = slice.NextChar(); var hasEscape = false; while (c != '\0' && (c != '"' || hasEscape)) { if (c == '\\' && !hasEscape) { hasEscape = true; } else { title.Append(c); hasEscape = false; } c = slice.NextChar(); } codeSnippet.Title = title.ToString().Trim(); if (c == '"') { slice.NextChar(); return(true); } return(false); }
/// <summary> /// Splits a slice into an IEnumerable of slices split on newlines /// </summary> /// <param name="slice">The slice to split</param> /// <returns>The line split into lines</returns> public static IEnumerable <StringSlice> SplitSliceToLines(StringSlice slice) { var sliceStart = slice.Start; while (!slice.IsEmpty) { if (slice.CurrentChar == '\n') { slice.NextChar(); yield return(new StringSlice(slice.Text, sliceStart, slice.Start - 1)); sliceStart = slice.Start; continue; } if (slice.CurrentChar == '\r' && slice.PeekChar(1) == '\n') { slice.Start += 2; yield return(new StringSlice(slice.Text, sliceStart, slice.Start - 1)); sliceStart = slice.Start; continue; } slice.NextChar(); } if (sliceStart != slice.Start) { yield return(new StringSlice(slice.Text, sliceStart, slice.Start - 1)); } }
private bool TryMatchAttributeValue(ref StringSlice slice, out string value, string extensionName, string attributeName, Action <string> logError) { value = string.Empty; var c = slice.CurrentChar; if (c != '"') { logError($"Invalid attribute \"{attributeName}\". Values must be enclosed in double quotes."); return(false); } var b = StringBuilderCache.Local(); c = slice.NextChar(); while (c != '"') { if (c.IsZero()) { logError($"Invalid attribute \"{attributeName}\". Values must be terminated with a double quote."); return(false); } b.Append(c); c = slice.NextChar(); } slice.NextChar(); value = b.ToString(); return(true); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { bool matchFound; char previous; matchFound = false; previous = slice.PeekCharExtra(-1); if (!previous.IsWhiteSpaceOrZero()) { return(false); } char current; int start; int end; slice.NextChar(); current = slice.CurrentChar; start = slice.Start; end = start; StringBuilder ep = new StringBuilder(); StringBuilder num = new StringBuilder(); while (current != ',') { end = slice.Start; ep.Append(current); current = slice.NextChar(); } current = slice.NextChar(); while (current != '}') { end = slice.Start; num.Append(current); current = slice.NextChar(); } current = slice.NextChar(); if (current.IsWhiteSpaceOrZero()) { int inlineStart; inlineStart = processor.GetSourcePosition(slice.Start, out int line, out int column); processor.Inline = new Caps() { Span = { Start = inlineStart, End = inlineStart + (end - start) + 1 }, Line = line, Column = column, CapEpisode = new StringSlice(ep.ToString()), CapNumber = new StringSlice(num.ToString()) }; matchFound = true; } return(matchFound); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { if (!ExtensionsHelper.MatchStart(ref slice, StartString, false)) { return(false); } var href = StringBuilderCache.Local(); var c = slice.CurrentChar; var saved = slice; var startChar = '\0'; int line; int column; if (c == '\'' || c == '"') { startChar = c; c = slice.NextChar(); } while (c != startChar && c != '>') { href.Append(c); c = slice.NextChar(); } if (startChar != '\0') { if (c != startChar) { return(false); } c = slice.NextChar(); } if (c != '>') { return(false); } slice.NextChar(); var xrefInline = new XrefInline { Href = href.ToString().Trim(), Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), Line = line, Column = column }; var htmlAttributes = xrefInline.GetAttributes(); htmlAttributes.AddPropertyIfNotExist("data-throw-if-not-resolved", "True"); processor.Inline = xrefInline; return(true); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { if (!slice.PeekCharExtra(-1).IsWhiteSpaceOrZero()) { return(false); //require whitespace/nothing before } var key = String.Empty; var issue = String.Empty; var current = slice.CurrentChar; //read as many uppercase characters as required - project key while (current.IsAlphaUpper()) { key += current; current = slice.NextChar(); } //require a '-' between key and issue number if (!current.Equals('-')) { return(false); } current = slice.NextChar(); //read as many numbers as required - issue number while (current.IsDigit()) { issue += current; current = slice.NextChar(); } if (!current.IsWhiteSpaceOrZero()) //must be followed by whitespace { return(false); } int line; int column; processor.Inline = new JiraLink() //create the link at the relevant position { Span = { Start = processor.GetSourcePosition(slice.Start, out line, out column) }, Line = line, Column = column, Issue = issue, Key = key }; processor.Inline.Span.End = processor.Inline.Span.Start + issue.Length + key.Length + 1; //+1 for the '-' return(true); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { bool matchFound; char next; matchFound = false; next = slice.PeekCharExtra(1); if (next == '<') { char current; int start; int end; slice.NextChar(); slice.NextChar(); // skip the opening pair current = slice.CurrentChar; start = slice.Start; end = start; while (current != '\0' && current != '>') { end++; current = slice.NextChar(); } if (end > start && current == '>' && slice.PeekCharExtra(1) == '>') { int inlineStart; end--; inlineStart = processor.GetSourcePosition(slice.Start, out int line, out int column); processor.Inline = new KeyboardInline { Span = { Start = inlineStart, End = inlineStart + (end - start) }, Line = line, Column = column, Text = new StringSlice(slice.Text, start, end) }; slice.NextChar(); slice.NextChar(); // skip the closing characters matchFound = true; } } return(matchFound); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // Allow preceding whitespace or `(` var pc = slice.PeekCharExtra(-1); if (!pc.IsWhiteSpaceOrZero() && pc != '(') { return(false); } var current = slice.CurrentChar; var startKey = slice.Start; var endKey = slice.Start; //read as many uppercase characters as required - project key while (current.IsAlphaUpper()) { endKey = slice.Start; current = slice.NextChar(); } //require a '-' between key and issue number if (!current.Equals('-')) { return(false); } current = slice.NextChar(); // skip - //read as many numbers as required - issue number if (!current.IsDigit()) { return(false); } var startIssue = slice.Start; var endIssue = slice.Start; while (current.IsDigit()) { endIssue = slice.Start; current = slice.NextChar(); } if (!current.IsWhiteSpaceOrZero() && current != ')') //can be followed only by a whitespace or `)` { return(false); } var jiraLink = new JiraLink() //create the link at the relevant position { Span = { Start = processor.GetSourcePosition(slice.Start, out int line, out int column) },
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // A tasklist is either // [ ] // or [x] or [X] var listItemBlock = processor.Block.Parent as ListItemBlock; if (listItemBlock == null) { return(false); } var startingPosition = slice.Start; var c = slice.NextChar(); if (!c.IsSpace() && c != 'x' && c != 'X') { return(false); } if (slice.NextChar() != ']') { return(false); } // Skip last ] slice.NextChar(); // Create the TaskList int line; int column; var taskItem = new TaskList() { Span = { Start = processor.GetSourcePosition(startingPosition, out line, out column) }, Line = line, Column = column, Checked = !c.IsSpace() }; taskItem.Span.End = taskItem.Span.Start + 2; processor.Inline = taskItem; // Add proper class for task list if (!string.IsNullOrEmpty(ListItemClass)) { listItemBlock.GetAttributes().AddClass(ListItemClass); } var listBlock = (ListBlock)listItemBlock.Parent; if (!string.IsNullOrEmpty(ListClass)) { listBlock.GetAttributes().AddClass(ListClass); } return(true); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { bool matchFound; char previous; matchFound = false; previous = slice.PeekCharExtra(-1); if (previous.IsWhiteSpaceOrZero() || previous == '(' || previous == '[') { char current; int start; int end; slice.NextChar(); // skip the # starting character current = slice.CurrentChar; start = slice.Start; end = start; // read as many digits as we can find, incrementing the slice length as we go while (current.IsDigit()) { end = slice.Start; current = slice.NextChar(); } // once we've ran out of digits, check to see what the next character is // to make sure this is a valid issue and nothing something random like #001Alpha if (current.IsWhiteSpaceOrZero() || current == ')' || current == ']') { int inlineStart; inlineStart = processor.GetSourcePosition(slice.Start, out int line, out int column); // and if we got here, then we've got a valid reference, so create our AST node // and assign it to the processor processor.Inline = new MantisLink { Span = { Start = inlineStart, End = inlineStart + (end - start) + 1 // add one to the length to account for the # starting character }, Line = line, Column = column, IssueNumber = new StringSlice(slice.Text, start, end) }; matchFound = true; } } return(matchFound); }
/// <summary> /// Parses a column header equivalent to the regexp: <code>\s*:\s*[delimiterChar]+\s*:\s*</code> /// </summary> /// <param name="slice">The text slice.</param> /// <param name="delimiterChar">The delimiter character (either `-` or `=`). If `\0`, it will detect the character (either `-` or `=`)</param> /// <param name="align">The alignment of the column.</param> /// <returns> /// <c>true</c> if parsing was successfull /// </returns> public static bool ParseColumnHeaderDetect(ref StringSlice slice, ref char delimiterChar, out TableColumnAlign?align) { align = null; slice.TrimStart(); var c = slice.CurrentChar; bool hasLeft = false; bool hasRight = false; if (c == ':') { hasLeft = true; slice.NextChar(); } slice.TrimStart(); c = slice.CurrentChar; // if we want to automatically detect if (delimiterChar == '\0') { if (c == '=' || c == '-') { delimiterChar = c; } else { return(false); } } // We expect at least one `-` delimiter char if (slice.CountAndSkipChar(delimiterChar) == 0) { return(false); } slice.TrimStart(); c = slice.CurrentChar; if (c == ':') { hasRight = true; slice.NextChar(); } slice.TrimStart(); align = hasLeft && hasRight ? TableColumnAlign.Center : hasRight ? TableColumnAlign.Right : hasLeft ? TableColumnAlign.Left : (TableColumnAlign?)null; return(true); }
/// <summary> /// Tries to match the specified slice. /// </summary> /// <param name="processor">The parser processor.</param> /// <param name="slice">The text slice.</param> /// <returns><c>true</c> if this parser found a match; <c>false</c> otherwise</returns> public override bool Match(InlineProcessor processor, ref StringSlice slice) { var c = slice.CurrentChar; var startPosition = processor.GetSourcePosition(slice.Start, out var line, out var column); var isImage = false; if (c == '!') { isImage = true; c = slice.NextChar(); if (c != LinkOpenChar) { return(false); } } switch (c) { case LinkOpenChar: if (slice.PeekChar() != LinkOpenChar) { return(false); } var saved = slice; var currentPosition = slice.Start; if (TryParseLink(ref slice, out var title, out var display, out var hasDisplay, out var autoDisplay, out var endPosition)) { processor.Inline = new WikiLinkDelimiterInline(this) { Type = DelimiterType.Open, AutoDisplay = autoDisplay, Display = display, HasDisplay = hasDisplay, Title = title, IsImage = isImage, Span = new SourceSpan(startPosition, processor.GetSourcePosition(slice.Start - 1)), Line = line, Column = column, }; slice = saved; if (endPosition == currentPosition) { slice.NextChar(); slice.NextChar(); } else { slice.Start = endPosition; slice.NextChar(); } }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { var _isMatch = false; int _start, _end; var _url = ""; char _current; var _fullSlice = slice.ToString().ToLower().TrimStart(OpeningCharacters); if (!slice.PeekCharExtra(-1).IsWhiteSpaceOrZero()) { return(_isMatch); } if (_configuration.BaseUrls.Where(u => _fullSlice.StartsWith(u)).Count() == 0) { return(_isMatch); } _start = slice.Start; _end = _start; _current = slice.NextChar(); while (_current != ']') { _url += _current; _end = slice.Start; _current = slice.NextChar(); } if (_current == ']') { slice.NextChar(); var _inlineStart = processor.GetSourcePosition(slice.Start, out int _line, out int _column); processor.Inline = new EmbeddedGist { Span = { Start = _inlineStart, End = _inlineStart + (_end - _start) + 1 }, Line = _line, Column = _column, Url = _url }; _isMatch = true; } return(_isMatch); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { if (slice.PeekCharExtra(1) != 'S' || slice.PeekCharExtra(2) != 'c' || slice.PeekCharExtra(3) != 'r' || slice.PeekCharExtra(4) != 'i' || slice.PeekCharExtra(5) != 'p' || slice.PeekCharExtra(6) != 't' || slice.PeekCharExtra(7) != 'C' || slice.PeekCharExtra(8) != 's' || slice.PeekCharExtra(9) != ' ') { return(false); } var content = String.Empty; var issue = String.Empty; char current; int counter = 1; //Account for the ` bool loop = true; for (int i = 0; i < slice.End && loop; i++) { current = slice.NextChar(); counter++; if (current == '`') { loop = false; } else { content += current; } } slice.NextChar(); counter++; int line; int column; processor.Inline = new ScriptCsInline() { Script = content.Substring(9) }; processor.Inline.Span = new SourceSpan() { Start = processor.GetSourcePosition(slice.Start, out line, out column) }; processor.Inline.Line = line; processor.Inline.Span.End = processor.Inline.Span.Start + counter; return(true); }
public void TestStringLineGroupWithModifiedStart() { var line1 = new StringSlice(" ABC"); line1.NextChar(); line1.NextChar(); var line2 = new StringSlice(" DEF "); line2.Trim(); var text = new StringLineGroup(4) {line1, line2}; var result = ToString(text.ToCharIterator()); TextAssert.AreEqual("ABC\nDEF", result); }
/// <summary> /// Tries to open a section tag using the slice /// </summary> /// <param name="processor">The processor</param> /// <param name="slice">The slice</param> /// <returns>The result of the match</returns> public override ParserState TryOpenBlock(Processor processor, ref StringSlice slice) { var tagStart = slice.Start - processor.CurrentTags.StartTag.Length; var index = slice.Start; while (slice[index].IsWhitespace()) { index++; } var match = slice[index]; if (match == OpeningTagDelimiter) { slice.Start = index + 1; // Skip delimiter while (slice.CurrentChar.IsWhitespace()) { slice.NextChar(); } var startIndex = slice.Start; // Take characters until closing tag while (!slice.IsEmpty && !slice.Match(processor.CurrentTags.EndTag)) { slice.NextChar(); } var sectionName = slice.ToString(startIndex, slice.Start).TrimEnd(); var contentStartPosition = slice.Start + processor.CurrentTags.EndTag.Length; var sectionTag = new SectionToken { SectionName = sectionName, StartPosition = tagStart, ContentStartPosition = contentStartPosition, Parser = this, IsClosed = false }; processor.CurrentToken = sectionTag; slice.Start = contentStartPosition; return(ParserState.Break); } return(ParserState.Continue); }
protected StringSlice ReadUntil(StringSlice slice, char until, out int end) { char current = slice.CurrentChar; int start = slice.Start; end = start; slice.NextChar(); while (current != until || current.IsWhiteSpaceOrZero()) { end = slice.Start; current = slice.NextChar(); } return(new StringSlice(slice.Text, start, end)); }
/// <summary> /// Returns the next character in the line being processed. Update <see cref="Start"/> and <see cref="Column"/>. /// </summary> /// <returns>The next character or `\0` if end of line is reached</returns> public char NextChar() { var c = Line.CurrentChar; if (c == '\t') { Column = CharHelper.AddTab(Column); } else { Column++; } return(Line.NextChar()); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { bool matchFound; char previous; matchFound = false; previous = slice.PeekCharExtra(-1); if (previous.IsWhiteSpaceOrZero() || previous == '(' || previous == '[') { char current; int start; int end; slice.NextChar(); current = slice.CurrentChar; start = slice.Start; end = start; while (current.IsDigit()) { end = slice.Start; current = slice.NextChar(); } if (current.IsWhiteSpaceOrZero() || current == ')' || current == ']') { int inlineStart; inlineStart = processor.GetSourcePosition(slice.Start, out int line, out int column); processor.Inline = new Mention { Span = { Start = inlineStart, End = inlineStart + (end - start) + 1 }, Line = line, Column = column, Username = new StringSlice(slice.Text, start, end) }; matchFound = true; } } return(matchFound); }
/// <summary> /// Try to create a block close tag /// </summary> /// <param name="processor">The processor</param> /// <param name="slice">the slice</param> /// <param name="token">the current block tag</param> /// <returns>If the close was successful</returns> public override bool TryClose(Processor processor, ref StringSlice slice, BlockToken token) { var sectionTag = (SectionToken)token; while (slice.CurrentChar.IsWhitespace()) { slice.NextChar(); } var blockStart = slice.Start - processor.CurrentTags.StartTag.Length; slice.Start = slice.Start + 1; // Skip the slash while (slice.CurrentChar.IsWhitespace()) { slice.NextChar(); } var startIndex = slice.Start; // Take characters until closing tag while (!slice.IsEmpty && !slice.Match(processor.CurrentTags.EndTag)) { slice.NextChar(); } var sectionName = slice.ToString(startIndex, slice.Start).TrimEnd(); if (sectionTag.SectionName == sectionName) { var tagEnd = slice.Start + processor.CurrentTags.EndTag.Length; var endTag = new SectionEndToken { SectionName = sectionName, EndPosition = tagEnd, ContentEndPosition = blockStart, IsClosed = true }; processor.CurrentToken = endTag; slice.Start += processor.CurrentTags.EndTag.Length; return(true); } throw new StubbleException($"Cannot close Block '{sectionName}' at {blockStart}. There is already an unclosed Block '{sectionTag.SectionName}'"); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { var previous = slice.PeekCharExtra(-1); //if (!previous.IsWhiteSpaceOrZero()) return false; slice.NextChar(); if (slice.CurrentChar != '>') { return(false); } var current = slice.NextChar(); var start = slice.Start; var end = start; while (current.IsDigit()) { end = slice.Start; current = slice.NextChar(); } if (!current.IsWhiteSpaceOrZero() && current.IsDigit()) { return(false); } var inlineStart = processor.GetSourcePosition(slice.Start, out var line, out var column); if (!int.TryParse(new StringSlice(slice.Text, start, end).ToString(), out var parsedId)) { return(false); } processor.Inline = new LinkToParsedModel { Span = { Start = inlineStart, End = inlineStart + (end - start) + 1 }, Line = line, Column = column, Id = parsedId, }; return(true); }
private BlockState TryParseTagType7(BlockProcessor state, StringSlice line, int startColumn, int startPosition) { var builder = StringBuilderCache.Local(); var c = line.CurrentChar; var result = BlockState.None; if ((c == '/' && HtmlHelper.TryParseHtmlCloseTag(ref line, builder)) || HtmlHelper.TryParseHtmlTagOpenTag(ref line, builder)) { // Must be followed by whitespace only bool hasOnlySpaces = true; c = line.CurrentChar; while (true) { if (c == '\0') { break; } if (!c.IsWhitespace()) { hasOnlySpaces = false; break; } c = line.NextChar(); } if (hasOnlySpaces) { result = CreateHtmlBlock(state, HtmlBlockType.NonInterruptingBlock, startColumn, startPosition); } } builder.Length = 0; return(result); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // Allow preceding whitespace var pc = slice.PeekCharExtra(-1); if (!pc.IsWhiteSpaceOrZero()) { return(false); } var current = slice.CurrentChar; var start = slice.Start; var end = slice.Start; // Read allowed characters while (current.IsAlphaNumeric() || current == '-' || current == '_' || current == '#') { end = slice.Start; current = slice.NextChar(); } var tag = new Hashtag { Span = { Start = processor.GetSourcePosition(slice.Start, out var line, out var column) },
public override bool Match(InlineProcessor processor, ref StringSlice slice) { if (!ExtensionsHelper.MatchStart(ref slice, StartString, false)) { return(false); } else { if (slice.CurrentChar == '-') { slice.NextChar(); } } var includeFile = new InclusionInline(); string title = null, path = null; if (!ExtensionsHelper.MatchLink(ref slice, ref title, ref path)) { return(false); } includeFile.Title = title; includeFile.IncludedFilePath = path; processor.Inline = includeFile; return(true); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { if (!slice.Match(m_StartTag)) { return(false); } var rawContent = new StringBuilder(); var current = slice.CurrentChar; while (!rawContent.ToString().EndsWith(m_EndTag)) { if (slice.IsEmpty) { return(false); } rawContent.Append(current); current = slice.NextChar(); } processor.Inline = new ProtectedTagsData(rawContent.ToString()); return(true); }