Skip to content

Commit

Permalink
Fix for twigphp/issues/3685 (markdown leading linebreaks and indentat…
Browse files Browse the repository at this point in the history
…ion)
  • Loading branch information
Sarke committed Apr 19, 2022
1 parent ab36653 commit ec9d565
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 37 deletions.
34 changes: 30 additions & 4 deletions extra/markdown-extra/MarkdownRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,37 @@ public function __construct(MarkdownInterface $converter)

public function convert(string $body): string
{
// remove indentation
if ($white = substr($body, 0, strspn($body, " \t\r\n\0\x0B"))) {
$body = preg_replace("{^$white}m", '', $body);
}
$body = $this->commonWhitespace($body);
$body = $this->removeIndentation($body);

return $this->converter->convert($body);
}

protected function commonWhitespace(string $body): string
{
return str_replace(["\t", "\0", "\x0B"], [' ', '', ''], $body);
}

protected function removeIndentation(string $body): string
{
$indent = $this->minIndentations($body);
if ($indent > 0) {
$body = preg_replace("{^ {{$indent}}}m", '', $body);
}

return $body;
}

protected function minIndentations(string $body): int
{
$non_empty_lines = preg_split('%(\r|\n)%', $body, -1, PREG_SPLIT_NO_EMPTY);

$list = [];
foreach ($non_empty_lines as $line)
{
$list[] = strspn($line, " ");
}

return min($list);
}
}
85 changes: 52 additions & 33 deletions extra/markdown-extra/Tests/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,60 +27,79 @@ class FunctionalTest extends TestCase
/**
* @dataProvider getMarkdownTests
*/
public function testMarkdown(string $template, string $expected): void
public function testMarkdown(string $markdown, string $expected): void
{
foreach ([LeagueMarkdown::class, ErusevMarkdown::class, /*MichelfMarkdown::class,*/ DefaultMarkdown::class] as $class) {
$twig = new Environment(new ArrayLoader([
'index' => $template,
'html' => <<<EOF
Hello
=====
$twig = $this->getTwig($class, [
'apply' => "{% apply markdown_to_html %}\n{$markdown}\n{% endapply %}",
'include' => "{{ include('md')|markdown_to_html }}",
'indent' => "{{ include('indent_md')|markdown_to_html }}",
'md' => $markdown,
'indent_md' => ltrim(str_replace("\n", "\n\t", "\n$markdown"), "\n"),
]);

Great!
EOF
]));
$twig->addExtension(new MarkdownExtension());
$twig->addRuntimeLoader(new class($class) implements RuntimeLoaderInterface {
private $class;
$twig_md = trim($twig->render('apply'));
$this->assertMatchesRegularExpression('{'.$expected.'}m', $twig_md);

public function __construct(string $class)
{
$this->class = $class;
}
$twig_md = trim($twig->render('include'));
$this->assertMatchesRegularExpression('{'.$expected.'}m', $twig_md);

public function load($c)
{
if (MarkdownRuntime::class === $c) {
return new $c(new $this->class());
}
}
});
$this->assertMatchesRegularExpression('{'.$expected.'}m', trim($twig->render('index')));
$twig_md = trim($twig->render('indent'));
$this->assertMatchesRegularExpression('{'.$expected.'}m', $twig_md);

$lib_md = trim((new $class)->convert($markdown));
$this->assertEquals($lib_md, $twig_md, "Twig output versus {$class} output.");
}
}

public function getMarkdownTests()
{
return [
[<<<EOF
{% apply markdown_to_html %}
Hello
=====
Great!
{% endapply %}
EOF
, "<h1>Hello</h1>\n+<p>Great!</p>"],

[<<<EOF
{% apply markdown_to_html %}
Hello
=====
Great!
{% endapply %}
Leading
Linebreak
EOF
, "<h1>Hello</h1>\n+<p>Great!</p>"],
["{{ include('html')|markdown_to_html }}", "<h1>Hello</h1>\n+<p>Great!</p>"],
, "<p>Leading</p>\n+<p>Linebreak</p>"],

[<<<EOF
Code
Paragraph
EOF
, "<pre><code>Code\n?</code></pre>\n+<p>Paragraph</p>"],
];
}

private function getTwig(string $class, array $templates): Environment
{
$twig = new Environment(new ArrayLoader($templates));
$twig->addExtension(new MarkdownExtension());
$twig->addRuntimeLoader(new class($class) implements RuntimeLoaderInterface {
private $class;

public function __construct(string $class)
{
$this->class = $class;
}

public function load($c)
{
if (MarkdownRuntime::class === $c)
{
return new $c(new $this->class());
}
}
});
return $twig;
}
}

0 comments on commit ec9d565

Please sign in to comment.