diff --git a/CHANGELOG.md b/CHANGELOG.md index de93b7aa7..f34f83a3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Fixed `bin/gpm selfupgrade` failing to report failed Grav update [#3116](https://github.com/getgrav/grav/issues/3116) * Fixed `bin/gpm selfupgrade` error on `Call to undefined method` [#3160](https://github.com/getgrav/grav/issues/3160) * Flex Pages: Fixed fatal error when trying to move a page to Root (/) [#3161](https://github.com/getgrav/grav/issues/3161) + * Fixed twig parsing errors in pages where twig is parsed after markdown [#3162](https://github.com/getgrav/grav/issues/3162) # v1.7.0 ## 01/19/2021 diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 4ec5f4a21..42338a74e 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -783,7 +783,7 @@ class Page implements PageInterface Grav::instance()->fireEvent('onPageContentProcessed', new Event(['page' => $this])); } else { if ($process_markdown) { - $this->processMarkdown(); + $this->processMarkdown($process_twig); } // Content Processed but not cached yet @@ -871,9 +871,10 @@ class Page implements PageInterface /** * Process the Markdown content. Uses Parsedown or Parsedown Extra depending on configuration * + * @param bool $keepTwig If true, content between twig tags will not be processed. * @return void */ - protected function processMarkdown() + protected function processMarkdown(bool $keepTwig = false) { /** @var Config $config */ $config = Grav::instance()['config']; @@ -905,7 +906,27 @@ class Page implements PageInterface $parsedown = new Parsedown($excerpts); } - $this->content = $parsedown->text($this->content); + $content = $this->content; + if ($keepTwig) { + // Base64 encode any twig. + $content = preg_replace_callback( + ['/({#)(.*?)(#})/mu', '/({{)(.*?)(}})/mu', '/({%)(.*?)(%})/mu'], + static function ($matches) { return $matches[1] . base64_encode($matches[2]) . $matches[3]; }, + $content + ); + } + $content = $parsedown->text($content); + + if ($keepTwig) { + // Base64 decode the encoded twig. + $content = preg_replace_callback( + ['/({#)(.*?)(#})/mu', '/({{)(.*?)(}})/mu', '/({%)(.*?)(%})/mu'], + static function ($matches) { return $matches[1] . base64_decode($matches[2]) . $matches[3]; }, + $content + ); + } + + $this->content = $content; } diff --git a/system/src/Grav/Framework/Flex/Pages/Traits/PageContentTrait.php b/system/src/Grav/Framework/Flex/Pages/Traits/PageContentTrait.php index 571fd64a8..f17f27626 100644 --- a/system/src/Grav/Framework/Flex/Pages/Traits/PageContentTrait.php +++ b/system/src/Grav/Framework/Flex/Pages/Traits/PageContentTrait.php @@ -734,6 +734,7 @@ trait PageContentTrait $grav->fireEvent('onPageContentProcessed', new Event(['page' => $this])); } else { if ($process_markdown) { + $options['keep_twig'] = $process_twig; $this->_content = $this->processMarkdown($this->_content, $options); } @@ -807,7 +808,28 @@ trait PageContentTrait $parsedown = new Parsedown($excerpts); } - return $parsedown->text($content); + $keepTwig = (bool)($options['keep_twig'] ?? false); + if ($keepTwig) { + // Base64 encode any twig. + $content = preg_replace_callback( + ['/({#)(.*?)(#})/mu', '/({{)(.*?)(}})/mu', '/({%)(.*?)(%})/mu'], + static function ($matches) { return $matches[1] . base64_encode($matches[2]) . $matches[3]; }, + $content + ); + } + + $content = $parsedown->text($content); + + if ($keepTwig) { + // Base64 decode the encoded twig. + $content = preg_replace_callback( + ['/({#)(.*?)(#})/mu', '/({{)(.*?)(}})/mu', '/({%)(.*?)(%})/mu'], + static function ($matches) { return $matches[1] . base64_decode($matches[2]) . $matches[3]; }, + $content + ); + } + + return $content; } abstract protected function loadHeaderProperty(string $property, $var, callable $filter);