MarkdownFormatter.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @package Grav\Framework\File\Formatter
  5. *
  6. * @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
  7. * @license MIT License; see LICENSE file for details.
  8. */
  9. namespace Grav\Framework\File\Formatter;
  10. use Grav\Framework\File\Interfaces\FileFormatterInterface;
  11. class MarkdownFormatter extends AbstractFormatter
  12. {
  13. /** @var FileFormatterInterface */
  14. private $headerFormatter;
  15. public function __construct(array $config = [], FileFormatterInterface $headerFormatter = null)
  16. {
  17. $config += [
  18. 'file_extension' => '.md',
  19. 'header' => 'header',
  20. 'body' => 'markdown',
  21. 'raw' => 'frontmatter',
  22. 'yaml' => ['inline' => 20]
  23. ];
  24. parent::__construct($config);
  25. $this->headerFormatter = $headerFormatter ?: new YamlFormatter($config['yaml']);
  26. }
  27. /**
  28. * Returns header field used in both encode() and decode().
  29. *
  30. * @return string
  31. */
  32. public function getHeaderField(): string
  33. {
  34. return $this->getConfig('header');
  35. }
  36. /**
  37. * Returns body field used in both encode() and decode().
  38. *
  39. * @return string
  40. */
  41. public function getBodyField(): string
  42. {
  43. return $this->getConfig('body');
  44. }
  45. /**
  46. * Returns raw field used in both encode() and decode().
  47. *
  48. * @return string
  49. */
  50. public function getRawField(): string
  51. {
  52. return $this->getConfig('raw');
  53. }
  54. /**
  55. * Returns header formatter object used in both encode() and decode().
  56. *
  57. * @return FileFormatterInterface
  58. */
  59. public function getHeaderFormatter(): FileFormatterInterface
  60. {
  61. return $this->headerFormatter;
  62. }
  63. /**
  64. * {@inheritdoc}
  65. * @see FileFormatterInterface::encode()
  66. */
  67. public function encode($data): string
  68. {
  69. $headerVar = $this->getHeaderField();
  70. $bodyVar = $this->getBodyField();
  71. $header = isset($data[$headerVar]) ? (array) $data[$headerVar] : [];
  72. $body = isset($data[$bodyVar]) ? (string) $data[$bodyVar] : '';
  73. // Create Markdown file with YAML header.
  74. $encoded = '';
  75. if ($header) {
  76. $encoded = "---\n" . trim($this->getHeaderFormatter()->encode($data['header'])) . "\n---\n\n";
  77. }
  78. $encoded .= $body;
  79. // Normalize line endings to Unix style.
  80. $encoded = preg_replace("/(\r\n|\r)/", "\n", $encoded);
  81. return $encoded;
  82. }
  83. /**
  84. * {@inheritdoc}
  85. * @see FileFormatterInterface::decode()
  86. */
  87. public function decode($data): array
  88. {
  89. $headerVar = $this->getHeaderField();
  90. $bodyVar = $this->getBodyField();
  91. $rawVar = $this->getRawField();
  92. // Define empty content
  93. $content = [
  94. $headerVar => [],
  95. $bodyVar => ''
  96. ];
  97. $headerRegex = "/^---\n(.+?)\n---\n{0,}(.*)$/uis";
  98. // Normalize line endings to Unix style.
  99. $data = preg_replace("/(\r\n|\r)/", "\n", $data);
  100. // Parse header.
  101. preg_match($headerRegex, ltrim($data), $matches);
  102. if(empty($matches)) {
  103. $content[$bodyVar] = $data;
  104. } else {
  105. // Normalize frontmatter.
  106. $frontmatter = preg_replace("/\n\t/", "\n ", $matches[1]);
  107. if ($rawVar) {
  108. $content[$rawVar] = $frontmatter;
  109. }
  110. $content[$headerVar] = $this->getHeaderFormatter()->decode($frontmatter);
  111. $content[$bodyVar] = $matches[2];
  112. }
  113. return $content;
  114. }
  115. }