コード例 #1
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
 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;
 }
コード例 #2
0
ファイル: SymbolTreeInfo.cs プロジェクト: natidea/roslyn
        /// <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;
                    }
                }
            }
        }
コード例 #3
0
        public override bool Match(InlineProcessor processor, ref StringSlice slice)
        {
            // We are matching the following characters:
            //
            // '    ‘ ’     &lsquo; &rsquo;     'left-single-quote', 'right-single-quote'
            // ''   “ ”     &ldquo; &rdquo;     'left-double-quote', 'right-double-quote'
            // "    “ ”     &ldquo; &rdquo;     'left-double-quote', 'right-double-quote'
            // << >>    « »     &laquo; &raquo;     'left-angle-quote', 'right-angle-quote'
            // ...  …   &hellip;    'ellipsis'

            // Special case: &ndash; and &mdash; are handle as a PostProcess step to avoid conflicts with pipetables header separator row
            // --   –   &ndash;     'ndash'
            // ---  —   &mdash;     '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);
        }
コード例 #4
0
 /// <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);
 }
コード例 #5
0
        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);
                }
            }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
 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());
 }
コード例 #9
0
 internal static CharacterSet Create(StringSlice values) => TakeArray(values.ToCharArray());
コード例 #10
0
 /// <summary>
 /// Sets the argument string.
 /// </summary>
 public void SetCommaSeparatedArgs(StringSlice inString)
 {
     StringArgument = inString;
 }
コード例 #11
0
        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),
                },
コード例 #12
0
        /// <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);
        }
コード例 #13
0
        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));
        }
コード例 #14
0
 internal string Dedup(StringSlice value) =>
 StringDeduper.GetEqualOrAdd(value.ToString());
コード例 #15
0
        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);
        }
コード例 #16
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
 public static int Compare(StringSlice strA, string strB)
 {
     return string.Compare(strA.str, strA.offset, strB, 0, Math.Max(strA.length, strB.Length));
 }
コード例 #17
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
 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);
 }
コード例 #18
0
 public static bool IsEscaped(StringSlice slice)
 {
     return(slice.PeekCharExtra(-1) == '\\');
 }
コード例 #19
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
        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;
                    }
                }


            }
        }
コード例 #20
0
 static string getText(StringSlice ss) => ss.Text.Substring(ss.Start, ss.Length);
コード例 #21
0
        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);
        }
コード例 #22
0
        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());
        }
コード例 #23
0
        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);
        }
コード例 #24
0
 public AsmTokenKind FindTokenKind(StringSlice slice)
 {
     return(slice.Length <= _maximumLength && _tokenKinds.TryGetValue(slice, out var tokenKind) ? tokenKind : AsmTokenKind.Identifier);
 }
コード例 #25
0
        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);
        }
コード例 #26
0
        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);
                    }
            }
        }
コード例 #27
0
ファイル: AutoLinkParser.cs プロジェクト: tys-hiroshi/markdig
        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);
        }
コード例 #28
0
ファイル: LiteralTagParser.cs プロジェクト: wizofaus/Stubble
        /// <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);
        }
コード例 #29
0
        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);
        }
コード例 #30
0
        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);
        }
コード例 #31
0
ファイル: SymbolTreeInfo.cs プロジェクト: natidea/roslyn
        /// <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;
        }
コード例 #32
0
        /// <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);
        }
コード例 #33
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
 public static int Compare(StringSlice strA, string strB, int strBindex, int length)
 {
     return string.Compare(strA.str, strA.offset, strB, strBindex, length);
 }
コード例 #34
0
        /// <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);
        }
コード例 #35
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
 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);
 }
コード例 #36
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LiteralInline"/> class.
 /// </summary>
 public LiteralInline()
 {
     Content = new StringSlice(null);
 }
コード例 #37
0
ファイル: Qa.cs プロジェクト: erisonliang/qizmt
 public static StringSlice Concat(StringSlice ssA, string sB)
 {
     return StringSlice.Prepare(ssA.ToString() + sB);
 }
コード例 #38
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LiteralInline"/> class.
 /// </summary>
 /// <param name="content">The content.</param>
 public LiteralInline(StringSlice content)
 {
     Content = content;
 }
コード例 #39
0
        private void ChangeEncoding(StringSlice encodingName)
        {
            var newEncoding = EncodingEx.GetEncodingByName(encodingName);

            ChangeEncoding(newEncoding);
        }
コード例 #40
0
        /// <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;
                }
            }
        }