Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FrontMatter extension only supports \n line endings #821

Closed
SeriousKen opened this issue Feb 26, 2022 · 1 comment
Closed

FrontMatter extension only supports \n line endings #821

SeriousKen opened this issue Feb 26, 2022 · 1 comment
Assignees
Labels
bug Something isn't working right fixed Fix has been implemented

Comments

@SeriousKen
Copy link

SeriousKen commented Feb 26, 2022

Version(s) affected

2.2

Description

The FrontMatter extension expects the document to use linux \n line endings and fails to split frontmatter and markdown when this is not the case. Both YAML and Markdown support all line endings.

How to reproduce

$markdown = new CommonMarkConverter();
$markdown->getEnvironment()->addExtension(new FrontMatterExtension());

$document = "---\r\ntitle: Hello World!\r\n---\r\n# This is some markdown";

$document = $markdown->convert($document);
echo $document->getContent();

Possible solution

final class FrontMatterParser implements FrontMatterParserInterface
{
    /** @psalm-readonly */
    private FrontMatterDataParserInterface $frontMatterParser;

    private const REGEX_FRONT_MATTER = '/^---\R.*?\R---\R/s';

    public function __construct(FrontMatterDataParserInterface $frontMatterParser)
    {
        $this->frontMatterParser = $frontMatterParser;
    }

    public function parse(string $markdownContent): MarkdownInputWithFrontMatter
    {
        $cursor = new Cursor($markdownContent);

        // Locate the front matter
        $frontMatter = $cursor->match(self::REGEX_FRONT_MATTER);
        if ($frontMatter === null) {
            return new MarkdownInputWithFrontMatter($markdownContent);
        }
        
        // Trim the last line (ending ---s and newline)
        $frontMatter = preg_replace('/---\R$/', '', $frontMatter);

        // Parse the resulting YAML data
        $data = $this->frontMatterParser->parse($frontMatter);

        // Advance through any remaining newlines which separated the front matter from the Markdown text
        $trailingNewlines = $cursor->match('/^\R+/');

        // Calculate how many lines the Markdown is offset from the front matter by counting the number of newlines
        // Don't forget to add 1 because we stripped one out when trimming the trailing delims
        $lineOffset = \preg_match_all('/\R/', $frontMatter . $trailingNewlines) + 1;

        return new MarkdownInputWithFrontMatter($cursor->getRemainder(), $lineOffset, $data);
    }
}

Additional context

No response

Did this project help you today? Did it make you happy in any way?

No response

@SeriousKen SeriousKen changed the title FrontMatter extension only supports \n FrontMatter extension only supports \n line endings Feb 26, 2022
@colinodell colinodell added the bug Something isn't working right label Feb 26, 2022
@colinodell colinodell self-assigned this Feb 26, 2022
@colinodell
Copy link
Member

Thanks for the bug report and proposed solution! I've released the fix in versions 2.0.4, 2.1.3, and 2.2.3. Cheers!

@colinodell colinodell added the fixed Fix has been implemented label Feb 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working right fixed Fix has been implemented
Projects
None yet
Development

No branches or pull requests

2 participants