예제 #1
0
        public override BlockState TryOpen(BlockProcessor processor)
        {
            if (processor.IsCodeIndent)
            {
                return(BlockState.None);
            }

            // Sample: [!code-javascript[Main](../jquery.js?name=testsnippet#tag "title")]
            var slice = processor.Line;

            if (!ExtensionsHelper.MatchStart(ref slice, StartString, false))
            {
                return(BlockState.None);
            }

            var codeSnippet = new CodeSnippet(this);

            MatchLanguage(processor, ref slice, ref codeSnippet);

            if (!MatchName(processor, ref slice, ref codeSnippet))
            {
                return(BlockState.None);
            }

            if (!MatchPath(processor, ref slice, ref codeSnippet))
            {
                return(BlockState.None);
            }

            MatchQuery(processor, ref slice, ref codeSnippet);

            MatchTitle(processor, ref slice, ref codeSnippet);

            ExtensionsHelper.SkipWhitespace(ref slice);
            if (slice.CurrentChar == ')')
            {
                slice.NextChar();
                ExtensionsHelper.SkipWhitespace(ref slice);
                if (slice.CurrentChar == ']')
                {
                    var codeSnippetEnd = slice.Start;
                    slice.NextChar();
                    ExtensionsHelper.SkipWhitespace(ref slice);
                    if (slice.CurrentChar == '\0')
                    {
                        // slice finished its task, re-use it for Raw content
                        slice.Start        = processor.Line.Start;
                        slice.End          = codeSnippetEnd;
                        codeSnippet.Raw    = slice.ToString();
                        codeSnippet.Column = processor.Column;

                        codeSnippet.SetAttributeString();
                        processor.NewBlocks.Push(codeSnippet);
                        return(BlockState.BreakDiscard);
                    }
                }
            }

            return(BlockState.None);
        }
예제 #2
0
        private bool MatchTitle(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet)
        {
            if (slice.CurrentChar != '"')
            {
                return(false);
            }

            var title     = StringBuilderCache.Local();
            var c         = slice.NextChar();
            var hasEscape = false;

            while (c != '\0' && (c != '"' || hasEscape))
            {
                if (c == '\\' && !hasEscape)
                {
                    hasEscape = true;
                }
                else
                {
                    title.Append(c);
                    hasEscape = false;
                }
                c = slice.NextChar();
            }

            codeSnippet.Title = title.ToString().Trim();

            if (c == '"')
            {
                slice.NextChar();
                return(true);
            }

            return(false);
        }
예제 #3
0
        private bool MatchQuery(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet)
        {
            var questionMarkMatched = MatchQuestionMarkQuery(processor, ref slice, ref codeSnippet);

            var bookMarkMatched = MatchBookMarkQuery(processor, ref slice, ref codeSnippet);

            return(questionMarkMatched || bookMarkMatched);
        }
예제 #4
0
        private bool MatchLanguage(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet)
        {
            if (slice.CurrentChar != '-')
            {
                return(false);
            }

            var language = StringBuilderCache.Local();
            var c        = slice.NextChar();

            while (c != '\0' && c != '[')
            {
                language.Append(c);
                c = slice.NextChar();
            }

            codeSnippet.Language = language.ToString().Trim();

            return(true);
        }
예제 #5
0
        private bool MatchPath(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet)
        {
            ExtensionsHelper.SkipWhitespace(ref slice);
            if (slice.CurrentChar != '(')
            {
                return(false);
            }
            var c = slice.NextChar();

            var bracketNeedToMatch = 0;

            var path      = StringBuilderCache.Local();
            var hasEscape = false;

            while (c != '\0' && (hasEscape || (c != '#' && c != '?' && c != '"' && (c != ')' || bracketNeedToMatch > 0))))
            {
                if (c == '\\' && !hasEscape)
                {
                    hasEscape = true;
                }
                else
                {
                    if (c == '(' && !hasEscape)
                    {
                        bracketNeedToMatch++;
                    }
                    if (c == ')' && !hasEscape)
                    {
                        bracketNeedToMatch--;
                    }
                    path.Append(c);
                    hasEscape = false;
                }
                c = slice.NextChar();
            }

            codeSnippet.CodePath = path.ToString().Trim();

            return(true);
        }
예제 #6
0
        private bool TryParseQuery(string queryString, ref CodeSnippet codeSnippet)
        {
            if (string.IsNullOrEmpty(queryString))
            {
                return(false);
            }

            var splitQueryItems = queryString.Split(new[] { '&' });

            int start = -1, end = -1;

            foreach (var queryItem in splitQueryItems)
            {
                var keyValueSplit = queryItem.Split(new[] { '=' });
                if (keyValueSplit.Length != 2)
                {
                    return(false);
                }
                var key   = keyValueSplit[0];
                var value = keyValueSplit[1];

                List <CodeRange> temp;
                switch (key.ToLower())
                {
                case "name":
                    codeSnippet.TagName = value;
                    break;

                case "start":
                    if (!int.TryParse(value, out start))
                    {
                        return(false);
                    }
                    end = start;
                    break;

                case "end":
                    if (!int.TryParse(value, out end))
                    {
                        return(false);
                    }
                    break;

                case "range":
                    if (!TryGetLineRanges(value, out temp))
                    {
                        return(false);
                    }

                    codeSnippet.CodeRanges = temp;
                    break;

                case "highlight":
                    if (!TryGetLineRanges(value, out temp))
                    {
                        return(false);
                    }

                    codeSnippet.HighlightRanges = temp;
                    break;

                case "dedent":
                    int dedent;

                    if (!int.TryParse(value, out dedent))
                    {
                        return(false);
                    }

                    codeSnippet.DedentLength = dedent;
                    break;

                default:
                    return(false);
                }
            }

            if (start != -1 && end != -1)
            {
                codeSnippet.StartEndRange = new CodeRange {
                    Start = start, End = end
                };
            }

            return(true);
        }
예제 #7
0
        private bool MatchBookMarkQuery(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet)
        {
            if (slice.CurrentChar != '#')
            {
                return(false);
            }

            var queryChar = slice.CurrentChar;
            var query     = StringBuilderCache.Local();
            var c         = slice.NextChar();

            while (c != '\0' && c != '"' && c != ')')
            {
                query.Append(c);
                c = slice.NextChar();
            }

            var queryString = query.ToString().Trim();

            CodeRange codeRange;

            if (TryGetLineRange(queryString, out codeRange))
            {
                codeSnippet.BookMarkRange = codeRange;
            }
            else
            {
                codeSnippet.TagName = queryString;
            }

            return(true);
        }
예제 #8
0
        private bool MatchQuestionMarkQuery(BlockProcessor processor, ref StringSlice slice, ref CodeSnippet codeSnippet)
        {
            if (slice.CurrentChar != '?')
            {
                return(false);
            }

            var queryChar = slice.CurrentChar;
            var query     = StringBuilderCache.Local();
            var c         = slice.NextChar();

            while (c != '\0' && c != '"' && c != ')' && c != '#')
            {
                query.Append(c);
                c = slice.NextChar();
            }

            var queryString = query.ToString().Trim();

            return(TryParseQuery(queryString, ref codeSnippet));
        }