/// <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); }