public static StringSlice Prepare(StringSlice ss, int offset, int length) { if (offset < 0 || length < 0 || offset + length > ss.length) { IndexOutOfRangeException ior = new IndexOutOfRangeException("StringSlice.Prepare(StringSlice{offset=" + ss.offset + ", length=" + ss.length + "}, offset=" + offset + ", length=" + length + ")"); throw new ArgumentOutOfRangeException("Specified argument was out of the range of valid values. Index out of bounds: " + ior.Message, ior); // Preserve the old exception type. } StringSlice ssnew; ssnew.str = ss.str; ssnew.offset = ss.offset + offset; ssnew.length = length; return ssnew; }
/// <summary> /// Gets all the node indices with matching names per the <paramref name="comparer" />. /// </summary> private IEnumerable<int> FindNodeIndices( string name, StringSliceComparer comparer) { // find any node that matches case-insensitively var startingPosition = BinarySearch(name); var nameSlice = new StringSlice(name); if (startingPosition != -1) { // yield if this matches by the actual given comparer if (comparer.Equals(nameSlice, GetNameSlice(startingPosition))) { yield return startingPosition; } int position = startingPosition; while (position > 0 && s_caseInsensitiveComparer.Equals(GetNameSlice(position - 1), nameSlice)) { position--; if (comparer.Equals(GetNameSlice(position), nameSlice)) { yield return position; } } position = startingPosition; while (position + 1 < _nodes.Length && s_caseInsensitiveComparer.Equals(GetNameSlice(position + 1), nameSlice)) { position++; if (comparer.Equals(GetNameSlice(position), nameSlice)) { yield return position; } } } }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // We are matching the following characters: // // ' ‘ ’ ‘ ’ 'left-single-quote', 'right-single-quote' // '' “ ” “ ” 'left-double-quote', 'right-double-quote' // " “ ” “ ” 'left-double-quote', 'right-double-quote' // << >> « » « » 'left-angle-quote', 'right-angle-quote' // ... … … 'ellipsis' // Special case: – and — are handle as a PostProcess step to avoid conflicts with pipetables header separator row // -- – – 'ndash' // --- — — 'mdash' var pc = slice.PeekCharExtra(-1); var c = slice.CurrentChar; var openingChar = c; var startingPosition = slice.Start; // undefined first var type = (SmartyPantType)0; switch (c) { case '\'': type = SmartyPantType.Quote; // We will resolve them at the end of parsing all inlines if (slice.PeekChar(1) == '\'') { slice.NextChar(); type = SmartyPantType.DoubleQuote; // We will resolve them at the end of parsing all inlines } break; case '"': type = SmartyPantType.DoubleQuote; break; case '<': if (slice.NextChar() == '<') { type = SmartyPantType.LeftAngleQuote; } break; case '>': if (slice.NextChar() == '>') { type = SmartyPantType.RightAngleQuote; } break; case '.': if (slice.NextChar() == '.' && slice.NextChar() == '.') { type = SmartyPantType.Ellipsis; } break; case '-': if (slice.NextChar() == '-') { var quotePants = GetOrCreateState(processor); quotePants.HasDash = true; return(false); } break; } // If it is not matched, early exit if (type == 0) { return(false); } // Skip char c = slice.NextChar(); bool canOpen; bool canClose; CharHelper.CheckOpenCloseDelimiter(pc, c, false, out canOpen, out canClose); bool postProcess = false; switch (type) { case SmartyPantType.Quote: postProcess = true; if (canOpen && !canClose) { type = SmartyPantType.LeftQuote; } else if (!canOpen && canClose) { type = SmartyPantType.RightQuote; } else { return(false); } break; case SmartyPantType.DoubleQuote: postProcess = true; if (canOpen && !canClose) { type = SmartyPantType.LeftDoubleQuote; } else if (!canOpen && canClose) { type = SmartyPantType.RightDoubleQuote; } else { return(false); } break; case SmartyPantType.LeftAngleQuote: postProcess = true; if (!canOpen || canClose) { return(false); } break; case SmartyPantType.RightAngleQuote: postProcess = true; if (canOpen || !canClose) { return(false); } break; case SmartyPantType.Ellipsis: if (canOpen || !canClose) { return(false); } break; } // Create the SmartyPant inline int line; int column; var pant = new SmartyPant() { Span = { Start = processor.GetSourcePosition(startingPosition, out line, out column) }, Line = line, Column = column, OpeningCharacter = openingChar, Type = type }; pant.Span.End = pant.Span.Start + slice.Start - startingPosition - 1; // We will check in a post-process step for balanaced open/close quotes if (postProcess) { var quotePants = GetOrCreateState(processor); // Register only if we don't have yet any quotes if (quotePants.Count == 0) { processor.Block.ProcessInlinesEnd += BlockOnProcessInlinesEnd; } quotePants.Add(pant); } processor.Inline = pant; return(true); }
/// <summary> /// Initializes a new instance of the <see cref="EmojiInline"/> class. /// </summary> /// <param name="content">The content.</param> public EmojiInline(string content) { Content = new StringSlice(content); }
private bool TryProcessLinkOrImage(InlineProcessor inlineState, ref StringSlice text) { LinkDelimiterInline?openParent = inlineState.Inline !.FirstParentOfType <LinkDelimiterInline>(); if (openParent is null) { return(false); } // If we do find one, but it’s not active, // we remove the inactive delimiter from the stack, // and return a literal text node ]. if (!openParent.IsActive) { inlineState.Inline = new LiteralInline() { Content = new StringSlice("["), Span = openParent.Span, Line = openParent.Line, Column = openParent.Column, }; openParent.ReplaceBy(inlineState.Inline); return(false); } // If we find one and it’s active, // then we parse ahead to see if we have // an inline link/image, reference link/image, // compact reference link/image, // or shortcut reference link/image var parentDelimiter = openParent.Parent; var savedText = text; if (text.CurrentChar == '(') { if (inlineState.TrackTrivia) { if (LinkHelper.TryParseInlineLinkTrivia( ref text, out string?url, out SourceSpan unescapedUrlSpan, out string?title, out SourceSpan unescapedTitleSpan, out char titleEnclosingCharacter, out SourceSpan linkSpan, out SourceSpan titleSpan, out SourceSpan triviaBeforeLink, out SourceSpan triviaAfterLink, out SourceSpan triviaAfterTitle, out bool urlHasPointyBrackets)) { var wsBeforeLink = new StringSlice(text.Text, triviaBeforeLink.Start, triviaBeforeLink.End); var wsAfterLink = new StringSlice(text.Text, triviaAfterLink.Start, triviaAfterLink.End); var wsAfterTitle = new StringSlice(text.Text, triviaAfterTitle.Start, triviaAfterTitle.End); var unescapedUrl = new StringSlice(text.Text, unescapedUrlSpan.Start, unescapedUrlSpan.End); var unescapedTitle = new StringSlice(text.Text, unescapedTitleSpan.Start, unescapedTitleSpan.End); // Inline Link var link = new LinkInline() { TriviaBeforeUrl = wsBeforeLink, Url = HtmlHelper.Unescape(url), UnescapedUrl = unescapedUrl, UrlHasPointyBrackets = urlHasPointyBrackets, TriviaAfterUrl = wsAfterLink, Title = HtmlHelper.Unescape(title), UnescapedTitle = unescapedTitle, TitleEnclosingCharacter = titleEnclosingCharacter, TriviaAfterTitle = wsAfterTitle, IsImage = openParent.IsImage, LabelSpan = openParent.LabelSpan, UrlSpan = inlineState.GetSourcePositionFromLocalSpan(linkSpan), TitleSpan = inlineState.GetSourcePositionFromLocalSpan(titleSpan), Span = new SourceSpan(openParent.Span.Start, inlineState.GetSourcePosition(text.Start - 1)), Line = openParent.Line, Column = openParent.Column, }; openParent.ReplaceBy(link); // Notifies processor as we are creating an inline locally inlineState.Inline = link; // Process emphasis delimiters inlineState.PostProcessInlines(0, link, null, false); // If we have a link (and not an image), // we also set all [ delimiters before the opening delimiter to inactive. // (This will prevent us from getting links within links.) if (!openParent.IsImage) { MarkParentAsInactive(parentDelimiter); } link.IsClosed = true; return(true); } } else { if (LinkHelper.TryParseInlineLink(ref text, out string?url, out string?title, out SourceSpan linkSpan, out SourceSpan titleSpan)) { // Inline Link var link = new LinkInline() { Url = HtmlHelper.Unescape(url), Title = HtmlHelper.Unescape(title), IsImage = openParent.IsImage, LabelSpan = openParent.LabelSpan, UrlSpan = inlineState.GetSourcePositionFromLocalSpan(linkSpan), TitleSpan = inlineState.GetSourcePositionFromLocalSpan(titleSpan), Span = new SourceSpan(openParent.Span.Start, inlineState.GetSourcePosition(text.Start - 1)), Line = openParent.Line, Column = openParent.Column, }; openParent.ReplaceBy(link); // Notifies processor as we are creating an inline locally inlineState.Inline = link; // Process emphasis delimiters inlineState.PostProcessInlines(0, link, null, false); // If we have a link (and not an image), // we also set all [ delimiters before the opening delimiter to inactive. // (This will prevent us from getting links within links.) if (!openParent.IsImage) { MarkParentAsInactive(parentDelimiter); } link.IsClosed = true; return(true); } } text = savedText; } var labelSpan = SourceSpan.Empty; string? label = null; SourceSpan labelWithTrivia = SourceSpan.Empty; bool isLabelSpanLocal = true; bool isShortcut = false; LocalLabel localLabel = LocalLabel.Local; // Handle Collapsed links if (text.CurrentChar == '[') { if (text.PeekChar() == ']') { label = openParent.Label; labelSpan = openParent.LabelSpan; isLabelSpanLocal = false; localLabel = LocalLabel.Empty; text.NextChar(); // Skip [ text.NextChar(); // Skip ] } } else { localLabel = LocalLabel.None; label = openParent.Label; isShortcut = true; } if (label != null || LinkHelper.TryParseLabelTrivia(ref text, true, out label, out labelSpan)) { labelWithTrivia = new SourceSpan(labelSpan.Start, labelSpan.End); if (isLabelSpanLocal) { labelSpan = inlineState.GetSourcePositionFromLocalSpan(labelSpan); } if (ProcessLinkReference(inlineState, text, label !, labelWithTrivia, isShortcut, labelSpan, openParent, inlineState.GetSourcePosition(text.Start - 1), localLabel)) { // Remove the open parent openParent.Remove(); if (!openParent.IsImage) { MarkParentAsInactive(parentDelimiter); } return(true); } else if (text.CurrentChar != ']' && text.CurrentChar != '[') { return(false); } }
public void Create_CreatesFlexiFigureBlock() { // Arrange const int dummyColumn = 2; var dummyLine = new StringSlice("dummyText", 3, 8); const string dummyBlockName = "dummyBlockName"; const string dummyResolvedBlockName = "dummyResolvedBlockName"; const int dummyFigureNumber = 5; const bool dummyGenerateID = true; const string dummyID = "dummyID"; const bool dummyReferenceLinkable = true; const bool dummyResolvedReferenceLinkable = false; const string dummyLinkLabelContent = "dummyLinkLabelContent"; const bool dummyLinkLabelContentSpecified = true; const bool dummyRenderName = true; const string dummyName = "dummyName"; const string dummyResolvedLinkLabelContent = "dummyResolvedLinkLabelContent"; BlockProcessor dummyBlockProcessor = MarkdigTypesFactory.CreateBlockProcessor(); dummyBlockProcessor.Column = dummyColumn; dummyBlockProcessor.Line = dummyLine; Mock <BlockParser> dummyBlockParser = _mockRepository.Create <BlockParser>(); var dummyAttributes = new ReadOnlyDictionary <string, string>(new Dictionary <string, string>()); Mock <IFlexiFigureBlockOptions> mockFlexiFigureBlockOptions = _mockRepository.Create <IFlexiFigureBlockOptions>(); mockFlexiFigureBlockOptions.Setup(f => f.BlockName).Returns(dummyBlockName); mockFlexiFigureBlockOptions.Setup(f => f.GenerateID).Returns(dummyGenerateID); mockFlexiFigureBlockOptions.Setup(f => f.ReferenceLinkable).Returns(dummyReferenceLinkable); mockFlexiFigureBlockOptions.Setup(f => f.RenderName).Returns(dummyRenderName); mockFlexiFigureBlockOptions.Setup(f => f.LinkLabelContent).Returns(dummyLinkLabelContent); mockFlexiFigureBlockOptions.Setup(f => f.Attributes).Returns(dummyAttributes); Mock <IOptionsService <IFlexiFigureBlockOptions, IFlexiFigureBlocksExtensionOptions> > mockOptionsService = _mockRepository. Create <IOptionsService <IFlexiFigureBlockOptions, IFlexiFigureBlocksExtensionOptions> >(); mockOptionsService.Setup(f => f.CreateOptions(dummyBlockProcessor)). Returns((mockFlexiFigureBlockOptions.Object, (IFlexiFigureBlocksExtensionOptions)null)); Mock <FlexiFigureBlockFactory> mockTestSubject = CreateMockFlexiFigureBlockFactory(mockOptionsService.Object); mockTestSubject.CallBase = true; mockTestSubject.Setup(t => t.ResolveBlockName(dummyBlockName)).Returns(dummyResolvedBlockName); mockTestSubject.Setup(t => t.GetFlexiFigureBlockNumber(dummyBlockProcessor)).Returns(dummyFigureNumber); mockTestSubject.Setup(t => t.ResolveID(dummyGenerateID, dummyFigureNumber, dummyAttributes)).Returns(dummyID); mockTestSubject.Setup(t => t.ResolveReferenceLinkable(dummyReferenceLinkable, dummyID)).Returns(dummyResolvedReferenceLinkable); mockTestSubject.Setup(t => t.IsLinkLabelContentSpecified(dummyLinkLabelContent)).Returns(dummyLinkLabelContentSpecified); mockTestSubject.Setup(t => t.ResolveName(dummyResolvedReferenceLinkable, dummyLinkLabelContentSpecified, dummyRenderName, dummyFigureNumber)).Returns(dummyName); mockTestSubject.Setup(t => t.ResolveLinkLabelContent(dummyResolvedReferenceLinkable, dummyLinkLabelContentSpecified, dummyName, dummyLinkLabelContent)).Returns(dummyResolvedLinkLabelContent); // Act FlexiFigureBlock result = mockTestSubject.Object.Create(dummyBlockProcessor, dummyBlockParser.Object); // Assert _mockRepository.VerifyAll(); Assert.Equal(dummyResolvedBlockName, result.BlockName); Assert.Equal(dummyName, result.Name); Assert.Equal(dummyRenderName, result.RenderName); Assert.Equal(dummyResolvedLinkLabelContent, result.LinkLabelContent); Assert.Equal(dummyID, result.ID); Assert.Same(dummyAttributes, result.Attributes); Assert.Same(dummyBlockParser.Object, result.Parser); Assert.Equal(dummyColumn, result.Column); Assert.Equal(dummyLine.Start, result.Span.Start); Assert.Equal(0, result.Span.End); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { var match = slice.CurrentChar; if (slice.PeekCharExtra(-1) == match) { return(false); } var startPosition = slice.Start; var openSticks = CountAndSkipChar(ref slice, match); var closeSticks = 0; var c = slice.CurrentChar; var builder = StringBuilderCache.Local(); // A { } string is a string of one or more `{` characters that is neither preceded nor followed by `{`. // A code span begins with a `{` string and ends with a `}` string of equal length. var contentEnd = -1; while (c != '\0') { if (c == '}') { contentEnd = slice.Start; closeSticks = CountAndSkipChar(ref slice, '}'); if (openSticks == closeSticks) { break; } builder.Append('}', closeSticks); c = slice.CurrentChar; } else { builder.Append(c); c = slice.NextChar(); } } if (closeSticks != openSticks) { return(false); } var content = builder.ToString(); var spanStart = processor.GetSourcePosition(startPosition, out var line, out var column); var spanEnd = processor.GetSourcePosition(slice.Start - 1); processor.Inline = new MdxCodeInline(content) { Span = new(spanStart, spanEnd), Line = line, Column = column, DelimiterCount = openSticks, }; return(true); }
public static StringSlice Concat(StringSlice ssA, StringSlice ssB) { if (object.ReferenceEquals(ssA.str, ssB.str)) { if (ssA.offset + ssA.length == ssB.offset) { return StringSlice.Prepare(ssA.str, ssA.offset, ssA.length + ssB.length); } } return StringSlice.Prepare(ssA.ToString() + ssB.ToString()); }
internal static CharacterSet Create(StringSlice values) => TakeArray(values.ToCharArray());
/// <summary> /// Sets the argument string. /// </summary> public void SetCommaSeparatedArgs(StringSlice inString) { StringArgument = inString; }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { var previousChar = slice.PeekCharExtra(-1); if (!previousChar.IsWhiteSpaceOrZero()) { return(false); } if (!slice.MatchLowercase("std.")) { return(false); } var startPosition = slice.Start; var endOffset = 0; while (slice.Start < slice.End && !Char.IsWhiteSpace(slice.CurrentChar) && slice.CurrentChar != ';') { slice.NextChar(); } if (slice.CurrentChar == ';') { endOffset += 1; } var text = slice.Text.Substring(startPosition, (slice.Start - startPosition) + 1).TrimEnd(' ', '\n', ';', '\t', '\r'); var sections = text.Split('#', ':'); if (sections.Length == 0 || sections.Length > 3) { return(false); } string module = null; string member = null; string displayText = null; switch (sections.Length) { case 1: module = sections[0]; displayText = module; break; case 2: module = sections[0]; if (text.Contains("#")) { member = sections[1]; } else // : { displayText = sections[1]; } break; case 3: module = sections[0]; member = sections[1]; displayText = sections[2]; break; default: break; } var inlineLink = new LinkInline { Span = { Start = processor.GetSourcePosition(startPosition, out int line, out int column), },
/// <summary> /// Tries to extra from the current position of a slice an HTML attributes {...} /// </summary> /// <param name="slice">The slice to parse.</param> /// <param name="attributes">The output attributes or null if not found or invalid</param> /// <returns><c>true</c> if parsing the HTML attributes was successful</returns> public static bool TryParse(ref StringSlice slice, out HtmlAttributes attributes) { attributes = null; if (slice.PeekCharExtra(-1) == '{') { return(false); } var line = slice; string id = null; List <string> classes = null; List <KeyValuePair <string, string> > properties = null; bool isValid = false; var c = line.NextChar(); while (true) { if (c == '}') { isValid = true; line.NextChar(); // skip } break; } if (c == '\0') { break; } bool isClass = c == '.'; if (c == '#' || isClass) { c = line.NextChar(); // Skip # var start = line.Start; // Get all non-whitespace characters following a # // But stop if we found a } or \0 while (c != '}' && c != '\0' && !c.IsWhitespace()) { c = line.NextChar(); } var end = line.Start - 1; if (end == start) { break; } var text = slice.Text.Substring(start, end - start + 1); if (isClass) { if (classes == null) { classes = new List <string>(); } classes.Add(text); } else { id = text; } continue; } if (!c.IsWhitespace()) { // Parse the attribute name if (!IsStartAttributeName(c)) { break; } var startName = line.Start; while (true) { c = line.NextChar(); if (!(c.IsAlphaNumeric() || c == '_' || c == ':' || c == '.' || c == '-')) { break; } } var name = slice.Text.Substring(startName, line.Start - startName); var hasSpace = c.IsSpaceOrTab(); // Skip any whitespaces line.TrimStart(); c = line.CurrentChar; // Handle boolean properties that are not followed by = if ((hasSpace && (c == '.' || c == '#' || IsStartAttributeName(c))) || c == '}') { if (properties == null) { properties = new List <KeyValuePair <string, string> >(); } // Add a null value for the property properties.Add(new KeyValuePair <string, string>(name, null)); continue; } // Else we expect a regular property if (line.CurrentChar != '=') { break; } // Go to next char, skip any spaces line.NextChar(); line.TrimStart(); int startValue = -1; int endValue = -1; c = line.CurrentChar; // Parse a quoted string if (c == '\'' || c == '"') { char openingStringChar = c; startValue = line.Start + 1; while (true) { c = line.NextChar(); if (c == '\0') { return(false); } if (c == openingStringChar) { break; } } endValue = line.Start - 1; c = line.NextChar(); // Skip closing opening string char } else { // Parse until we match a space or a special html character startValue = line.Start; bool valid = false; while (true) { if (c == '\0') { return(false); } if (c.IsWhitespace() || c == '}') { break; } c = line.NextChar(); valid = true; } endValue = line.Start - 1; if (!valid) { break; } } var value = slice.Text.Substring(startValue, endValue - startValue + 1); if (properties == null) { properties = new List <KeyValuePair <string, string> >(); } properties.Add(new KeyValuePair <string, string>(name, value)); continue; } c = line.NextChar(); } if (isValid) { attributes = new HtmlAttributes() { Id = id, Classes = classes, Properties = properties }; // Assign back the current processor of the line to slice = line; } return(isValid); }
private BlockState TryParseTagType16(BlockProcessor state, StringSlice line, int startColumn, int startPosition) { char c; c = line.CurrentChar; if (c == '!') { c = line.NextChar(); if (c == '-' && line.PeekChar(1) == '-') { return(CreateHtmlBlock(state, HtmlBlockType.Comment, startColumn, startPosition)); // group 2 } if (c.IsAlphaUpper()) { return(CreateHtmlBlock(state, HtmlBlockType.DocumentType, startColumn, startPosition)); // group 4 } if (c == '[' && line.Match("CDATA[", 1)) { return(CreateHtmlBlock(state, HtmlBlockType.CData, startColumn, startPosition)); // group 5 } return(BlockState.None); } if (c == '?') { return(CreateHtmlBlock(state, HtmlBlockType.ProcessingInstruction, startColumn, startPosition)); // group 3 } var hasLeadingClose = c == '/'; if (hasLeadingClose) { c = line.NextChar(); } var tag = new char[10]; var count = 0; for (; count < tag.Length; count++) { if (!c.IsAlphaNumeric()) { break; } tag[count] = Char.ToLowerInvariant(c); c = line.NextChar(); } if ( !(c == '>' || (!hasLeadingClose && c == '/' && line.PeekChar(1) == '>') || c.IsWhitespace() || c == '\0')) { return(BlockState.None); } if (count == 0) { return(BlockState.None); } var tagName = new string(tag, 0, count); var tagIndex = Array.BinarySearch(HtmlTags, tagName, StringComparer.Ordinal); if (tagIndex < 0) { return(BlockState.None); } // Cannot start with </script </pre or </style if ((tagIndex == 45 || tagIndex == 46 || tagIndex == 49)) { if (c == '/' || hasLeadingClose) { return(BlockState.None); } return(CreateHtmlBlock(state, HtmlBlockType.ScriptPreOrStyle, startColumn, startPosition)); } return(CreateHtmlBlock(state, HtmlBlockType.InterruptingBlock, startColumn, startPosition)); }
internal string Dedup(StringSlice value) => StringDeduper.GetEqualOrAdd(value.ToString());
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // First, some definitions. A delimiter run is either a sequence of one or more * characters that // is not preceded or followed by a * character, or a sequence of one or more _ characters that // is not preceded or followed by a _ character. var delimiterChar = slice.CurrentChar; var emphasisDesc = emphasisMap[delimiterChar]; var pc = slice.PeekCharExtra(-1); if (pc == delimiterChar && slice.PeekCharExtra(-2) != '\\') { return(false); } var startPosition = slice.Start; int delimiterCount = 0; char c; do { delimiterCount++; c = slice.NextChar(); } while (c == delimiterChar); // If the emphasis doesn't have the minimum required character if (delimiterCount < emphasisDesc.MinimumCount) { return(false); } // Calculate Open-Close for current character bool canOpen; bool canClose; CharHelper.CheckOpenCloseDelimiter(pc, c, emphasisDesc.EnableWithinWord, out canOpen, out canClose); // We have potentially an open or close emphasis if (canOpen || canClose) { var delimiterType = DelimiterType.Undefined; if (canOpen) { delimiterType |= DelimiterType.Open; } if (canClose) { delimiterType |= DelimiterType.Close; } int line; int column; var delimiter = new EmphasisDelimiterInline(this, emphasisDesc) { DelimiterCount = delimiterCount, Type = delimiterType, Span = new SourceSpan(processor.GetSourcePosition(startPosition, out line, out column), processor.GetSourcePosition(slice.Start - 1)), Column = column, Line = line, }; processor.Inline = delimiter; return(true); } // We don't have an emphasis return(false); }
public static int Compare(StringSlice strA, string strB) { return string.Compare(strA.str, strA.offset, strB, 0, Math.Max(strA.length, strB.Length)); }
public static int Compare(StringSlice strA, string strB, StringComparison comparisonType) { return string.Compare(strA.str, strA.offset, strB, 0, Math.Max(strA.length, strB.Length), comparisonType); }
public static bool IsEscaped(StringSlice slice) { return(slice.PeekCharExtra(-1) == '\\'); }
public static StringSlice SliceNextPart(ref StringSlice text) { StringSlice s = text.TrimStart(MyWhitespace); if (s.Length > 0) { if (s[0] == '(' || s[0] == ')' || s[0] == ',' || s[0] == ';') { StringSlice result = s.Substring(0, 1); text = s.Substring(1); return result; } if (s[0] == '\'') { bool prevsquot = false; for (int i = 1; ; i++) { if (i >= s.Length) { if (prevsquot) { StringSlice result = s; text = StringSlice.Prepare(); return result; } throw new Exception("Expected terminating single quote: " + s); } if (s[i] == '\'') { if (prevsquot) { prevsquot = false; } else { prevsquot = true; } } else if (prevsquot) { if (s[i] == ' ') { StringSlice result = s.Substring(0, i); text = s.Substring(i + 1); return result; } else // Text directly after. { StringSlice result = s.Substring(0, i); text = s.Substring(i); return result; } } } } } for (int i = 0; ; i++) { if (i >= s.Length) { StringSlice result = s; text = StringSlice.Prepare(); return result; } if (char.IsWhiteSpace(s[i])) { StringSlice result = s.Substring(0, i); text = s.Substring(i + 1); return result; } if (!char.IsLetterOrDigit(s[i]) && '_' != s[i] && '.' != s[i]) { if (i > 0) { StringSlice result = s.Substring(0, i); text = s.Substring(i); return result; } { i++; // Return this symbol. StringSlice result = s.Substring(0, i); text = s.Substring(i); return result; } } } }
static string getText(StringSlice ss) => ss.Text.Substring(ss.Start, ss.Length);
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // Only working on Paragraph block if (!(processor.Block is ParagraphBlock)) { return(false); } var c = slice.CurrentChar; // If we have not a delimiter on the first line of a paragraph, don't bother to continue // tracking other delimiters on following lines var tableState = processor.ParserStates[Index] as TableState; bool isFirstLineEmpty = false; var position = processor.GetSourcePosition(slice.Start, out int globalLineIndex, out int column); var localLineIndex = globalLineIndex - processor.LineIndex; if (tableState is null) { // A table could be preceded by an empty line or a line containing an inline // that has not been added to the stack, so we consider this as a valid // start for a table. Typically, with this, we can have an attributes {...} // starting on the first line of a pipe table, even if the first line // doesn't have a pipe if (processor.Inline != null && (localLineIndex > 0 || c == '\n' || c == '\r')) { return(false); } if (processor.Inline is null) { isFirstLineEmpty = true; } // Else setup a table processor tableState = new TableState(); processor.ParserStates[Index] = tableState; } if (c == '\n' || c == '\r') { if (!isFirstLineEmpty && !tableState.LineHasPipe) { tableState.IsInvalidTable = true; } tableState.LineHasPipe = false; lineBreakParser.Match(processor, ref slice); tableState.LineIndex++; if (!isFirstLineEmpty) { tableState.ColumnAndLineDelimiters.Add(processor.Inline !); tableState.EndOfLines.Add(processor.Inline !); } } else { processor.Inline = new PipeTableDelimiterInline(this) { Span = new SourceSpan(position, position), Line = globalLineIndex, Column = column, LocalLineIndex = localLineIndex }; var deltaLine = localLineIndex - tableState.LineIndex; if (deltaLine > 0) { tableState.IsInvalidTable = true; } tableState.LineHasPipe = true; tableState.LineIndex = localLineIndex; slice.NextChar(); // Skip the `|` character tableState.ColumnAndLineDelimiters.Add(processor.Inline); } return(true); }
string ParseString(bool useCache) { // ditch opening quote _pos++; int stringStartPos = _pos; bool parsing = true; bool hasEscapes = false; while (parsing) { if (_pos >= _length) { break; } char c = _chars[_pos++]; switch (c) { case '"': parsing = false; break; case '\\': if (_pos >= _length) { parsing = false; break; } if (!hasEscapes) { _builder.Length = 0; _builder.Append(_chars, stringStartPos, _pos - stringStartPos - 1); hasEscapes = true; } char escaped = _chars[_pos++]; switch (escaped) { case '"': case '\\': case '/': _builder.Append(escaped); break; case 'b': _builder.Append('\b'); break; case 'f': _builder.Append('\f'); break; case 'n': _builder.Append('\n'); break; case 'r': _builder.Append('\r'); break; case 't': _builder.Append('\t'); break; case 'u': if (_pos + 3 >= _length) { parsing = false; break; } uint accum = 0; for (int i = 0; i < 4; i++) { var hexByte = _chars[_pos++]; uint hexDigit = (uint)ParseHexByte(hexByte); if (i > 0) { accum *= 16; } accum += hexDigit; } _builder.Append((char)accum); // TODO: surrogate pairs break; } break; default: if (hasEscapes) { _builder.Append(c); } break; } } int length = _pos - stringStartPos - 1; if (length <= 0) { return(string.Empty); } if (hasEscapes) { return(_builder.ToString()); } var slice = new StringSlice(_chars, stringStartPos, length); return(useCache ? StringFromCache(slice) : slice.ToString()); }
private bool ProcessLinkReference( InlineProcessor state, StringSlice text, string label, SourceSpan labelWithriviaSpan, bool isShortcut, SourceSpan labelSpan, LinkDelimiterInline parent, int endPosition, LocalLabel localLabel) { if (!state.Document.TryGetLinkReferenceDefinition(label, out LinkReferenceDefinition? linkRef)) { return(false); } Inline?link = null; // Try to use a callback directly defined on the LinkReferenceDefinition if (linkRef.CreateLinkInline != null) { link = linkRef.CreateLinkInline(state, linkRef, parent.FirstChild); } // Create a default link if the callback was not found if (link is null) { var labelWithTrivia = new StringSlice(text.Text, labelWithriviaSpan.Start, labelWithriviaSpan.End); // Inline Link link = new LinkInline() { Url = HtmlHelper.Unescape(linkRef.Url), Title = HtmlHelper.Unescape(linkRef.Title), Label = label, LabelSpan = labelSpan, LabelWithTrivia = labelWithTrivia, LinkRefDefLabel = linkRef.Label, LinkRefDefLabelWithTrivia = linkRef.LabelWithTrivia, LocalLabel = localLabel, UrlSpan = linkRef.UrlSpan, IsImage = parent.IsImage, IsShortcut = isShortcut, Reference = linkRef, Span = new SourceSpan(parent.Span.Start, endPosition), Line = parent.Line, Column = parent.Column, }; } if (link is ContainerInline containerLink) { var child = parent.FirstChild; if (child is null) { child = new LiteralInline() { Content = StringSlice.Empty, IsClosed = true, // Not exact but we leave it like this Span = parent.Span, Line = parent.Line, Column = parent.Column, }; containerLink.AppendChild(child); } else { // Insert all child into the link while (child != null) { var next = child.NextSibling; child.Remove(); containerLink.AppendChild(child); child = next; } } } link.IsClosed = true; // Process emphasis delimiters state.PostProcessInlines(0, link, null, false); state.Inline = link; return(true); }
public AsmTokenKind FindTokenKind(StringSlice slice) { return(slice.Length <= _maximumLength && _tokenKinds.TryGetValue(slice, out var tokenKind) ? tokenKind : AsmTokenKind.Identifier); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // The following methods are inspired by the "An algorithm for parsing nested emphasis and links" // at the end of the CommonMark specs. var c = slice.CurrentChar; var startPosition = processor.GetSourcePosition(slice.Start, out int line, out int column); bool isImage = false; if (c == '!') { isImage = true; c = slice.NextChar(); if (c != '[') { return(false); } } string? label; SourceSpan labelWithTriviaSpan = SourceSpan.Empty; switch (c) { case '[': // If this is not an image, we may have a reference link shortcut // so we try to resolve it here var saved = slice; SourceSpan labelSpan; // If the label is followed by either a ( or a [, this is not a shortcut if (processor.TrackTrivia) { if (LinkHelper.TryParseLabelTrivia(ref slice, out label, out labelSpan)) { labelWithTriviaSpan.Start = labelSpan.Start; // skip opening [ labelWithTriviaSpan.End = labelSpan.End; // skip closing ] if (!processor.Document.ContainsLinkReferenceDefinition(label)) { label = null; } } } else { if (LinkHelper.TryParseLabel(ref slice, out label, out labelSpan)) { if (!processor.Document.ContainsLinkReferenceDefinition(label)) { label = null; } } } slice = saved; // Else we insert a LinkDelimiter slice.NextChar(); var labelWithTrivia = new StringSlice(slice.Text, labelWithTriviaSpan.Start, labelWithTriviaSpan.End); processor.Inline = new LinkDelimiterInline(this) { Type = DelimiterType.Open, Label = label, LabelWithTrivia = labelWithTrivia, LabelSpan = processor.GetSourcePositionFromLocalSpan(labelSpan), IsImage = isImage, Span = new SourceSpan(startPosition, processor.GetSourcePosition(slice.Start - 1)), Line = line, Column = column }; return(true); case ']': slice.NextChar(); if (processor.Inline != null) { if (TryProcessLinkOrImage(processor, ref slice)) { return(true); } } // If we don’t find one, we return a literal slice node ]. // (Done after by the LiteralInline parser) return(false); } // We don't have an emphasis return(false); }
static IMessage MakeMessageInternal(TextMessageCapture capture, XmlFormatInfo formatInfo, IRegex bodyRe, ref IMatch bodyReMatch, MessagesBuilderCallback callback, XsltArgumentList transformArgs, DateTime sourceTime, ITimeOffsets timeOffsets) { int nrOfSequentialFailures = 0; int maxNrOfSequentialFailures = 10; for (; ;) { StringBuilder messageBuf = new StringBuilder(); messageBuf.AppendFormat("<root {0}>", formatInfo.NSDeclaration.ToString()); messageBuf.Append(capture.HeaderBuffer, capture.HeaderMatch.Index, capture.HeaderMatch.Length); if (bodyRe != null) { if (!bodyRe.Match(capture.BodyBuffer, capture.BodyIndex, capture.BodyLength, ref bodyReMatch)) { return(null); } messageBuf.Append(capture.BodyBuffer, bodyReMatch.Index, bodyReMatch.Length); } else { messageBuf.Append(capture.BodyBuffer, capture.BodyIndex, capture.BodyLength); } messageBuf.Append("</root>"); callback.SetCurrentPosition(capture.BeginPosition, capture.EndPosition); if (formatInfo.ViewOptions.RawViewAllowed) { callback.SetRawText(StringSlice.Concat(capture.MessageHeaderSlice, capture.MessageBodySlice).Trim()); } //this.owner.xslExt.SetSourceTime(this.owner.MediaLastModified); todo? string messageStr = messageBuf.ToString(); using (FactoryWriter factoryWriter = new FactoryWriter(callback, timeOffsets, formatInfo.ViewOptions.WrapLineLength)) using (XmlReader xmlReader = XmlReader.Create(new StringReader(messageStr), xmlReaderSettings)) { try { if (formatInfo.IsNativeFormat) { factoryWriter.WriteNode(xmlReader, false); } else { formatInfo.Transform.Transform(xmlReader, transformArgs, factoryWriter); } nrOfSequentialFailures = 0; } catch (XmlException) { if (capture.IsLastMessage) { // There might be incomplete XML at the end of the stream. Ignore it. return(null); } else { if (nrOfSequentialFailures < maxNrOfSequentialFailures) { ++nrOfSequentialFailures; // Try to parse the next message if it's not the end of the stream continue; } else { throw; } } } var ret = factoryWriter.GetOutput(); if (ret == null) { throw new XsltException( "Normalization XSLT produced no output"); } return(ret); } } }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // Previous char must be a whitespace or a punctuation var previousChar = slice.PeekCharExtra(-1); if (!previousChar.IsWhiteSpaceOrZero() && ValidPreviousCharacters.IndexOf(previousChar) == -1) { return(false); } List <char> pendingEmphasis; // Check that an autolink is possible in the current context if (!IsAutoLinkValidInCurrentContext(processor, out pendingEmphasis)) { return(false); } var startPosition = slice.Start; int domainOffset = 0; var c = slice.CurrentChar; // Precheck URL switch (c) { case 'h': if (slice.MatchLowercase("ttp://", 1)) { domainOffset = 7; // http:// } else if (slice.MatchLowercase("ttps://", 1)) { domainOffset = 8; // https:// } else { return(false); } break; case 'f': if (!slice.MatchLowercase("tp://", 1)) { return(false); } domainOffset = 6; // ftp:// break; case 'm': if (!slice.MatchLowercase("ailto:", 1)) { return(false); } break; case 'w': if (!slice.MatchLowercase("ww.", 1)) // We won't match http:/www. or /www.xxx { return(false); } domainOffset = 4; // www. break; } // Parse URL string link; if (!LinkHelper.TryParseUrl(ref slice, out link, true)) { return(false); } // If we have any pending emphasis, remove any pending emphasis characters from the end of the link if (pendingEmphasis != null) { for (int i = link.Length - 1; i >= 0; i--) { if (pendingEmphasis.Contains(link[i])) { slice.Start--; } else { if (i < link.Length - 1) { link = link.Substring(0, i + 1); } break; } } } // Post-check URL switch (c) { case 'h': if (string.Equals(link, "http://", StringComparison.OrdinalIgnoreCase) || string.Equals(link, "https://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'f': if (string.Equals(link, "ftp://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'm': int atIndex = link.IndexOf('@'); if (atIndex == -1 || atIndex == 7) // mailto:@ - no email part { return(false); } domainOffset = atIndex + 1; break; } if (!LinkHelper.IsValidDomain(link, domainOffset)) { return(false); } int line; int column; var inline = new LinkInline() { Span = { Start = processor.GetSourcePosition(startPosition, out line, out column), }, Line = line, Column = column, Url = c == 'w' ? "http://" + link : link, IsClosed = true, IsAutoLink = true, }; var skipFromBeginning = c == 'm' ? 7 : 0; // For mailto: skip "mailto:" for content inline.Span.End = inline.Span.Start + link.Length - 1; inline.UrlSpan = inline.Span; inline.AppendChild(new LiteralInline() { Span = inline.Span, Line = line, Column = column, Content = new StringSlice(slice.Text, startPosition + skipFromBeginning, startPosition + link.Length - 1), IsClosed = true }); processor.Inline = inline; return(true); }
/// <summary> /// Parse a literal tag from the slice /// </summary> /// <param name="processor">The processor</param> /// <param name="slice">The slice</param> /// <returns>The result of the match</returns> public LiteralTagResult Match(Processor processor, ref StringSlice slice) { var c = slice.CurrentChar; var start = slice.Start; var index = slice.Start; var tag = new LiteralToken { ContentStartPosition = index }; processor.CurrentToken = tag; while (c != '\0') { if (slice.Match(processor.CurrentTags.StartTag)) { if (tag.ContentStartPosition == slice.Start) { return(LiteralTagResult.NoContent); } tag.ContentEndPosition = slice.Start; tag.IsWhitespace = new StringSlice(slice.Text, tag.ContentStartPosition, tag.ContentEndPosition - 1).IsEmptyOrWhitespace(); tag.IsClosed = true; return(LiteralTagResult.TagStart); } // If this is whitespace then increase the start pointer by one if (c.IsWhitespace()) { if (!processor.HasSeenNonSpaceOnLine) { processor.LineIndent++; } start++; } else { processor.HasSeenNonSpaceOnLine = true; } if (slice.IsNewLine()) { int endIndex; if (c == '\n') { endIndex = slice.Start + 1; } else { endIndex = slice.Start + 2; } tag.ContentEndPosition = endIndex; tag.IsWhitespace = new StringSlice(slice.Text, tag.ContentStartPosition, tag.ContentEndPosition - 1).IsEmptyOrWhitespace(); tag.IsClosed = true; return(LiteralTagResult.NewLine); } c = slice.NextChar(); } if (tag.ContentStartPosition == slice.Start) { return(LiteralTagResult.NoContent); } tag.ContentEndPosition = slice.Start; tag.IsWhitespace = new StringSlice(slice.Text, tag.ContentStartPosition, tag.ContentEndPosition - 1).IsEmptyOrWhitespace(); tag.IsClosed = true; return(LiteralTagResult.EndOfFile); }
private bool TryProcessLinkOrImage(InlineProcessor inlineState, ref StringSlice text) { LinkDelimiterInline openParent = inlineState.Inline.FirstParentOfType <LinkDelimiterInline>(); if (openParent is null) { return(false); } // If we do find one, but it’s not active, // we remove the inactive delimiter from the stack, // and return a literal text node ]. if (!openParent.IsActive) { inlineState.Inline = new LiteralInline() { Content = new StringSlice("["), Span = openParent.Span, Line = openParent.Line, Column = openParent.Column, }; openParent.ReplaceBy(inlineState.Inline); return(false); } // If we find one and it’s active, // then we parse ahead to see if we have // an inline link/image, reference link/image, // compact reference link/image, // or shortcut reference link/image var parentDelimiter = openParent.Parent; var savedText = text; if (text.CurrentChar == '(') { if (LinkHelper.TryParseInlineLink(ref text, out string url, out string title, out SourceSpan linkSpan, out SourceSpan titleSpan)) { // Inline Link var link = new LinkInline() { Url = HtmlHelper.Unescape(url), Title = HtmlHelper.Unescape(title), IsImage = openParent.IsImage, LabelSpan = openParent.LabelSpan, UrlSpan = inlineState.GetSourcePositionFromLocalSpan(linkSpan), TitleSpan = inlineState.GetSourcePositionFromLocalSpan(titleSpan), Span = new SourceSpan(openParent.Span.Start, inlineState.GetSourcePosition(text.Start - 1)), Line = openParent.Line, Column = openParent.Column, }; openParent.ReplaceBy(link); // Notifies processor as we are creating an inline locally inlineState.Inline = link; // Process emphasis delimiters inlineState.PostProcessInlines(0, link, null, false); // If we have a link (and not an image), // we also set all [ delimiters before the opening delimiter to inactive. // (This will prevent us from getting links within links.) if (!openParent.IsImage) { MarkParentAsInactive(parentDelimiter); } link.IsClosed = true; return(true); } text = savedText; } var labelSpan = SourceSpan.Empty; string label = null; bool isLabelSpanLocal = true; bool isShortcut = false; // Handle Collapsed links if (text.CurrentChar == '[') { if (text.PeekChar() == ']') { label = openParent.Label; labelSpan = openParent.LabelSpan; isLabelSpanLocal = false; text.NextChar(); // Skip [ text.NextChar(); // Skip ] } } else { label = openParent.Label; isShortcut = true; } if (label != null || LinkHelper.TryParseLabel(ref text, true, out label, out labelSpan)) { if (isLabelSpanLocal) { labelSpan = inlineState.GetSourcePositionFromLocalSpan(labelSpan); } if (ProcessLinkReference(inlineState, label, isShortcut, labelSpan, openParent, inlineState.GetSourcePosition(text.Start - 1))) { // Remove the open parent openParent.Remove(); if (!openParent.IsImage) { MarkParentAsInactive(parentDelimiter); } return(true); } else if (text.CurrentChar != ']' && text.CurrentChar != '[') { return(false); } } // We have a nested [ ] // firstParent.Remove(); // The opening [ will be transformed to a literal followed by all the children of the [ var literal = new LiteralInline() { Span = openParent.Span, Content = new StringSlice(openParent.IsImage ? "![" : "[") }; inlineState.Inline = openParent.ReplaceBy(literal); return(false); }
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); } int line; int column; var jiraLink = new JiraLink() //create the link at the relevant position { Span = { Start = processor.GetSourcePosition(slice.Start, out line, out column) }, Line = line, Column = column, Issue = new StringSlice(slice.Text, startIssue, endIssue), ProjectKey = new StringSlice(slice.Text, startKey, endKey), }; jiraLink.Span.End = jiraLink.Span.Start + (endIssue - startKey); // Builds the Url var builder = StringBuilderCache.Local(); builder.Append(_baseUrl).Append('/').Append(jiraLink.ProjectKey).Append('-').Append(jiraLink.Issue); jiraLink.Url = builder.ToString(); // Builds the Label builder.Length = 0; builder.Append(jiraLink.ProjectKey).Append('-').Append(jiraLink.Issue); jiraLink.AppendChild(new LiteralInline(builder.ToString())); if (_options.OpenInNewWindow) { jiraLink.GetAttributes().AddProperty("target", "blank"); } processor.Inline = jiraLink; return(true); }
/// <summary> /// Searches for a name in the ordered list that matches per the <see cref="s_caseInsensitiveComparer" />. /// </summary> private int BinarySearch(string name) { var nameSlice = new StringSlice(name); int max = _nodes.Length - 1; int min = 0; while (max >= min) { int mid = min + ((max - min) >> 1); var comparison = s_caseInsensitiveComparer.Compare(GetNameSlice(mid), nameSlice); if (comparison < 0) { min = mid + 1; } else if (comparison > 0) { max = mid - 1; } else { return mid; } } return -1; }
/// <summary> /// Attempts to evaluate if all conditions described by the given string are true. /// </summary> static public bool TryEvaluate(this IVariantResolver inResolver, object inContext, StringSlice inEvalData, IMethodCache inInvoker = null) { if (inEvalData.IsWhitespace) { return(true); } StringSlice.ISplitter splitter = QuoteAwareSplitter ?? (QuoteAwareSplitter = new StringUtils.ArgsList.Splitter(false)); VariantComparison comp; foreach (var group in inEvalData.EnumeratedSplit(splitter, StringSplitOptions.RemoveEmptyEntries)) { if (!VariantComparison.TryParse(group, out comp) || !comp.Evaluate(inResolver, inContext, inInvoker)) { return(false); } } return(true); }
public static int Compare(StringSlice strA, string strB, int strBindex, int length) { return string.Compare(strA.str, strA.offset, strB, strBindex, length); }
/// <summary> /// Attempts to apply one or more modifications, described by the given string. /// </summary> static public bool TryModify(this IVariantResolver inResolver, object inContext, StringSlice inModifyData, IMethodCache inInvoker = null) { if (inModifyData.IsWhitespace) { return(true); } StringSlice.ISplitter splitter = QuoteAwareSplitter ?? (QuoteAwareSplitter = new StringUtils.ArgsList.Splitter(false)); bool bSuccess = true; VariantModification mod; foreach (var group in inModifyData.EnumeratedSplit(splitter, StringSplitOptions.RemoveEmptyEntries)) { if (!VariantModification.TryParse(group, out mod) || !mod.Execute(inResolver, inContext, inInvoker)) { bSuccess = false; } } return(bSuccess); }
public static int Compare(StringSlice strA, string strB, int strBindex, int length, StringComparison comparisonType) { return string.Compare(strA.str, strA.offset, strB, strBindex, length, comparisonType); }
/// <summary> /// Initializes a new instance of the <see cref="LiteralInline"/> class. /// </summary> public LiteralInline() { Content = new StringSlice(null); }
public static StringSlice Concat(StringSlice ssA, string sB) { return StringSlice.Prepare(ssA.ToString() + sB); }
/// <summary> /// Initializes a new instance of the <see cref="LiteralInline"/> class. /// </summary> /// <param name="content">The content.</param> public LiteralInline(StringSlice content) { Content = content; }
private void ChangeEncoding(StringSlice encodingName) { var newEncoding = EncodingEx.GetEncodingByName(encodingName); ChangeEncoding(newEncoding); }
/// <summary> /// Closes the block using the provided close tag /// </summary> /// <param name="processor">The processor</param> /// <param name="token">The open tag</param> /// <param name="closeToken">the closing tag</param> /// <param name="content">the content the tags were parsed from</param> public override void EndBlock(Processor processor, BlockToken token, BlockCloseToken closeToken, StringSlice content) { var sectionTag = token as InvertedSectionToken; var sectionEndTag = closeToken as SectionEndToken; if (sectionTag != null && sectionEndTag != null) { if (sectionTag.SectionName.Equals(sectionEndTag.SectionName)) { sectionTag.Tags = processor.CurrentTags; sectionTag.EndPosition = sectionEndTag.EndPosition; sectionTag.IsClosed = true; } } }