예제 #1
0
        /// <summary>
        /// Tries to match a block opening.
        /// </summary>
        /// <param name="processor">The parser processor.</param>
        /// <returns>The result of the match</returns>
        public override BlockState TryOpen(BlockProcessor processor)
        {
            // We expect no indentation for a fenced code block.
            if (processor.IsCodeIndent)
            {
                return(BlockState.None);
            }

            // Only accept a frontmatter at the beginning of the file
            if (processor.Start != 0)
            {
                return(BlockState.None);
            }

            int  count = 0;
            var  line  = processor.Line;
            char c     = line.CurrentChar;

            // Must consist of exactly three dashes
            while (c == '-' && count < 4)
            {
                count++;
                c = line.NextChar();
            }

            // If three dashes (optionally followed by whitespace)
            // this is a YAML front matter block
            if (count == 3 && (c == '\0' || c.IsWhitespace()) && line.TrimEnd())
            {
                bool hasFullYamlFrontMatter = false;
                // We make sure that there is a closing frontmatter somewhere in the document
                // so here we work on the full document instead of just the line
                var fullLine = new StringSlice(line.Text, line.Start, line.Text.Length - 1);
                c = fullLine.CurrentChar;
                while (c != '\0')
                {
                    c = fullLine.NextChar();
                    if (c == '\n' || c == '\r')
                    {
                        var nc = fullLine.PeekChar();
                        if (c == '\r' && nc == '\n')
                        {
                            c = fullLine.NextChar();
                        }
                        nc = fullLine.PeekChar();
                        if (nc == '-')
                        {
                            if (fullLine.NextChar() == '-' && fullLine.NextChar() == '-' && fullLine.NextChar() == '-' && (fullLine.NextChar() == '\0' || fullLine.SkipSpacesToEndOfLineOrEndOfDocument()))
                            {
                                hasFullYamlFrontMatter = true;
                                break;
                            }
                        }
                        else if (nc == '.')
                        {
                            if (fullLine.NextChar() == '.' && fullLine.NextChar() == '.' && fullLine.NextChar() == '.' && (fullLine.NextChar() == '\0' || fullLine.SkipSpacesToEndOfLineOrEndOfDocument()))
                            {
                                hasFullYamlFrontMatter = true;
                                break;
                            }
                        }
                    }
                }

                if (hasFullYamlFrontMatter)
                {
                    // Create a front matter block
                    var block = this.CreateFrontMatterBlock(processor);
                    block.Column     = processor.Column;
                    block.Span.Start = 0;
                    block.Span.End   = line.Start;

                    // Store the number of matched string into the context
                    processor.NewBlocks.Push(block);

                    // Discard the current line as it is already parsed
                    return(BlockState.ContinueDiscard);
                }
            }

            return(BlockState.None);
        }