diff --git a/src/flextype/core/Serializers/Frontmatter.php b/src/flextype/core/Serializers/Frontmatter.php index 08365901..51af4b06 100644 --- a/src/flextype/core/Serializers/Frontmatter.php +++ b/src/flextype/core/Serializers/Frontmatter.php @@ -86,7 +86,7 @@ class Frontmatter $headerSerializer = 'yaml'; } - $decode = static function (string $input) use ($headerSerializer) { + $decode = static function (string $input) use ($headerSerializer, $allowed) { // Remove UTF-8 BOM if it exists. $input = ltrim($input, "\xef\xbb\xbf"); @@ -96,11 +96,27 @@ class Frontmatter // Parse Frontmatter and Body $parts = preg_split('/^[\s\r\n]?---[\s\r\n]?$/sm', PHP_EOL . strings($input)->trimLeft()->toString()); - if (count($parts) < 3) { - return ['content' => strings($input)->trim()->toString()]; + // Replace empty array item with empty string and reindex array. + if (empty($parts[0])) { + unset($parts[0]); + $parts = array_values(array_filter($parts)); } + + // Check for custom frontmatter header serializers + if (strings(strings($parts[0])->lines()[1])->trim()->contains('---')) { + $headerSerializer = strings(strings($parts[0])->lines()[1])->trim()->after('---')->toString(); + + $parts[0] = strings($parts[0])->replaceFirst('---' . $headerSerializer, '')->toString(); - return serializers()->{$headerSerializer}()->decode(strings($parts[1])->trim()->toString(), false) + ['content' => strings(implode(PHP_EOL . '---' . PHP_EOL, array_slice($parts, 2)))->trim()->toString()]; + if (! in_array($headerSerializer, $allowed)) { + $headerSerializer = 'yaml'; + } + } + + $frontmatter = serializers()->{$headerSerializer}()->decode(strings($parts[0])->trim()->toString(), false); + $content = ['content' => strings($parts[1] ?? '')->trim()->toString()]; + + return (is_array($frontmatter) ? $frontmatter : []) + $content; }; if ($cache === true && registry()->get('flextype.settings.cache.enabled') === true) { diff --git a/src/flextype/settings.yaml b/src/flextype/settings.yaml index 03c7988e..4c933895 100644 --- a/src/flextype/settings.yaml +++ b/src/flextype/settings.yaml @@ -454,8 +454,6 @@ slugify: # neon.encode.flags: The flag can be 1, which will create multiline output. # # phparray.decode.cache: Cache result data or no. Default is true. -# -# phpcode.decode.cache: Cache result data or no. Default is true. serializers: json: decode: @@ -489,11 +487,11 @@ serializers: cache: true header: serializer: yaml - allowed: ['yaml', 'json', 'neon'] + allowed: ['yaml', 'json', 'json5', 'neon'] encode: header: serializer: yaml - allowed: ['yaml', 'json', 'neon'] + allowed: ['yaml', 'json', 'json5', 'neon'] neon: decode: cache: true diff --git a/tests/fixtures/serializers/frontmatter-json.md b/tests/fixtures/serializers/frontmatter-json.md new file mode 100644 index 00000000..2cddfbe1 --- /dev/null +++ b/tests/fixtures/serializers/frontmatter-json.md @@ -0,0 +1,4 @@ +---json +{"title": "Frontmatter JSON"} +--- +Content is here. \ No newline at end of file diff --git a/tests/fixtures/serializers/frontmatter-json5.md b/tests/fixtures/serializers/frontmatter-json5.md new file mode 100644 index 00000000..74c44b67 --- /dev/null +++ b/tests/fixtures/serializers/frontmatter-json5.md @@ -0,0 +1,4 @@ +---json5 +{title: "Frontmatter JSON5"} +--- +Content is here. \ No newline at end of file diff --git a/tests/fixtures/serializers/frontmatter-neon.md b/tests/fixtures/serializers/frontmatter-neon.md new file mode 100644 index 00000000..e616a83d --- /dev/null +++ b/tests/fixtures/serializers/frontmatter-neon.md @@ -0,0 +1,4 @@ +---neon +title: "Frontmatter NEON" +--- +Content is here. \ No newline at end of file diff --git a/tests/fixtures/serializers/frontmatter-yaml.md b/tests/fixtures/serializers/frontmatter-yaml.md new file mode 100644 index 00000000..b5389067 --- /dev/null +++ b/tests/fixtures/serializers/frontmatter-yaml.md @@ -0,0 +1,4 @@ +---yaml +title: "Frontmatter YAML" +--- +Content is here. \ No newline at end of file diff --git a/tests/fixtures/settings/settings.yaml b/tests/fixtures/settings/settings.yaml index a01142af..4707ecda 100644 --- a/tests/fixtures/settings/settings.yaml +++ b/tests/fixtures/settings/settings.yaml @@ -476,11 +476,11 @@ serializers: cache: true header: serializer: yaml - allowed: ['yaml', 'json', 'neon'] + allowed: ['yaml', 'json', 'json5', 'neon'] encode: header: serializer: yaml - allowed: ['yaml', 'json', 'neon'] + allowed: ['yaml', 'json', 'json5', 'neon'] neon: decode: cache: true diff --git a/tests/src/flextype/core/Serializers/FrontmatterTest.php b/tests/src/flextype/core/Serializers/FrontmatterTest.php index 57ca5767..5efa5587 100644 --- a/tests/src/flextype/core/Serializers/FrontmatterTest.php +++ b/tests/src/flextype/core/Serializers/FrontmatterTest.php @@ -8,6 +8,7 @@ test('encode', function () { serializers()->frontmatter() ->encode(['title' => 'Foo', 'content' => 'Content is here.'])); + }); test('decode', function () { @@ -15,6 +16,26 @@ test('decode', function () { 'content' => 'Content is here.'], serializers()->frontmatter() ->decode($string = filesystem()->file(ROOT_DIR . '/tests/fixtures/serializers/frontmatter.md')->get())); + + $this->assertEquals(['title' => 'Frontmatter YAML', + 'content' => 'Content is here.'], + serializers()->frontmatter() + ->decode($string = filesystem()->file(ROOT_DIR . '/tests/fixtures/serializers/frontmatter-yaml.md')->get())); + + $this->assertEquals(['title' => 'Frontmatter JSON', + 'content' => 'Content is here.'], + serializers()->frontmatter() + ->decode($string = filesystem()->file(ROOT_DIR . '/tests/fixtures/serializers/frontmatter-json.md')->get())); + + $this->assertEquals(['title' => 'Frontmatter JSON5', + 'content' => 'Content is here.'], + serializers()->frontmatter() + ->decode($string = filesystem()->file(ROOT_DIR . '/tests/fixtures/serializers/frontmatter-json5.md')->get())); + + $this->assertEquals(['title' => 'Frontmatter NEON', + 'content' => 'Content is here.'], + serializers()->frontmatter() + ->decode($string = filesystem()->file(ROOT_DIR . '/tests/fixtures/serializers/frontmatter-neon.md')->get())); }); test('get cache ID', function () { diff --git a/tests/src/flextype/core/Serializers/YamlTest.php b/tests/src/flextype/core/Serializers/YamlTest.php index c2abf141..ed049441 100644 --- a/tests/src/flextype/core/Serializers/YamlTest.php +++ b/tests/src/flextype/core/Serializers/YamlTest.php @@ -14,6 +14,11 @@ test('decode', function () { 'content' => 'Bar'], serializers()->yaml() ->decode("title: Foo\ncontent: Bar")); + + $this->assertEquals(['title' => 'Foo', + 'content' => 'Bar'], + serializers()->yaml() + ->decode("{\"title\": \"Foo\", \"content\": \"Bar\"}")); }); test('get cache ID', function () {