From 1540d7483ef74cf4eeec0321e87d2a3c7fa4d585 Mon Sep 17 00:00:00 2001 From: Marco Almeida Date: Wed, 18 Feb 2026 13:45:34 +0000 Subject: [PATCH 1/6] Refactor generate_frontmatter to allow 3rd party to add lines to the markdown header content --- src/Output/ContentRenderer.php | 77 +++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/src/Output/ContentRenderer.php b/src/Output/ContentRenderer.php index 5fcc2f7..da89b0f 100644 --- a/src/Output/ContentRenderer.php +++ b/src/Output/ContentRenderer.php @@ -74,46 +74,83 @@ public function render(WP_Post $post): string { * @return string The YAML frontmatter block. */ private function generate_frontmatter(WP_Post $post): string { - $lines = ['---']; + + $lines = array(); + $content_lines = array(); + + // YAML starter + $lines[] = '---'; // Title (always included) $title = get_the_title($post); - $lines[] = 'title: "' . $this->escape_yaml($title) . '"'; + $content_lines['title']['content'] = $this->escape_yaml($title); // Date (always included) $date = get_the_date('Y-m-d', $post); - $lines[] = 'date: ' . $date; + $content_lines['date']['content'] = $date; // Author (always included) $author = get_the_author_meta('display_name', $post->post_author); - $lines[] = 'author: "' . $this->escape_yaml($author) . '"'; + $content_lines['author']['content'] = $this->escape_yaml($author); // Featured image (only if set) $featured_image = get_the_post_thumbnail_url($post->ID, 'full'); if ($featured_image) { - $lines[] = 'featured_image: "' . $this->escape_yaml($featured_image) . '"'; + $content_lines['featured_image']['content'] = $this->escape_yaml($featured_image); } - // Categories (only if present and not WP_Error) - $categories = get_the_terms($post->ID, 'category'); - if ($categories && !is_wp_error($categories)) { - $lines[] = 'categories:'; - foreach ($categories as $category) { - $lines[] = ' - name: "' . $this->escape_yaml($category->name) . '"'; - $lines[] = ' url: "' . $this->get_term_markdown_url($category) . '"'; + $taxonommies = array( + 'category' => 'categories', + 'post_tag' => 'tags', + ); + $taxonomies = apply_filters('markdown_alternate_frontmatter_taxonomies', $taxonommies, $post); + + // Loop through taxonomies and add to content lines (only if present and not WP_Error) + foreach ($taxonomies as $taxonomy => $key) { + $terms = get_the_terms($post->ID, $taxonomy); + if ($terms && !is_wp_error($terms)) { + $content_lines[$key]['items'] = array(); + foreach ($terms as $term) { + $content_lines[$key]['items'][] = array( + 'name' => $this->escape_yaml($term->name), + 'url' => $this->get_term_markdown_url($term), + ); + } } } - // Tags (only if present and not WP_Error) - $tags = get_the_terms($post->ID, 'post_tag'); - if ($tags && !is_wp_error($tags)) { - $lines[] = 'tags:'; - foreach ($tags as $tag) { - $lines[] = ' - name: "' . $this->escape_yaml($tag->name) . '"'; - $lines[] = ' url: "' . $this->get_term_markdown_url($tag) . '"'; + // Add content lines to lines + foreach ($content_lines as $key => $value) { + if (isset($value['content'])) { + switch( $key ) { + case 'date': + $lines[] = $key . ': ' . $value['content']; + break; + default: + $lines[] = $key . ': "' . $value['content'] . '"'; + break; + + } + } + if (isset($value['items']) && is_array($value['items'])) { + $lines[] = $key . ':'; + $i = 0; + foreach ($value['items'] as $item) { + $i = 0; + foreach($item as $item_key => $item_value) { + $item[$item_key] = $this->escape_yaml($item_value); + if ( $i === 0 ) { + $lines[] = ' - ' . $item_key . ': "' . $item[$item_key] . '"'; + } else { + $lines[] = ' ' . $item_key . ': "' . $item[$item_key] . '"'; + } + $i++; + } + } } } - + + // YAML ender $lines[] = '---'; return implode("\n", $lines); From ce640c2fd0ee539db7e55ec2ad720a6ff1736c28 Mon Sep 17 00:00:00 2001 From: Marco Almeida Date: Wed, 18 Feb 2026 13:46:57 +0000 Subject: [PATCH 2/6] Allow 3rd party to modify content lines before they are added to the frontmatter --- src/Output/ContentRenderer.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Output/ContentRenderer.php b/src/Output/ContentRenderer.php index da89b0f..704a3ff 100644 --- a/src/Output/ContentRenderer.php +++ b/src/Output/ContentRenderer.php @@ -118,6 +118,9 @@ private function generate_frontmatter(WP_Post $post): string { } } } + + // Allow 3rd party to modify content lines before they are added to the frontmatter + $content_lines = apply_filters('markdown_alternate_frontmatter_content_lines', $content_lines, $post); // Add content lines to lines foreach ($content_lines as $key => $value) { @@ -149,6 +152,9 @@ private function generate_frontmatter(WP_Post $post): string { } } } + + // Allow 3rd party to add lines + $lines = apply_filters('markdown_alternate_frontmatter_lines', $lines, $post); // YAML ender $lines[] = '---'; From 880b292914e96287bdb701d8d3defeea5ef94990 Mon Sep 17 00:00:00 2001 From: Marco Almeida Date: Wed, 18 Feb 2026 14:01:30 +0000 Subject: [PATCH 3/6] Add comments --- src/Output/ContentRenderer.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Output/ContentRenderer.php b/src/Output/ContentRenderer.php index 704a3ff..0fc0599 100644 --- a/src/Output/ContentRenderer.php +++ b/src/Output/ContentRenderer.php @@ -99,6 +99,7 @@ private function generate_frontmatter(WP_Post $post): string { $content_lines['featured_image']['content'] = $this->escape_yaml($featured_image); } + // Taxonomies (categories and tags by default, but filterable) $taxonommies = array( 'category' => 'categories', 'post_tag' => 'tags', @@ -124,6 +125,7 @@ private function generate_frontmatter(WP_Post $post): string { // Add content lines to lines foreach ($content_lines as $key => $value) { + // Single content line (like title, date, author, featured_image) if (isset($value['content'])) { switch( $key ) { case 'date': @@ -135,6 +137,7 @@ private function generate_frontmatter(WP_Post $post): string { } } + // Multiple items (like categories and tags) if (isset($value['items']) && is_array($value['items'])) { $lines[] = $key . ':'; $i = 0; From 9b8898acb297178112d582aea4580bc53b61faef Mon Sep 17 00:00:00 2001 From: Marco Almeida Date: Wed, 18 Feb 2026 14:17:46 +0000 Subject: [PATCH 4/6] Implement content types --- src/Output/ContentRenderer.php | 57 +++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/src/Output/ContentRenderer.php b/src/Output/ContentRenderer.php index 0fc0599..33429b1 100644 --- a/src/Output/ContentRenderer.php +++ b/src/Output/ContentRenderer.php @@ -83,20 +83,32 @@ private function generate_frontmatter(WP_Post $post): string { // Title (always included) $title = get_the_title($post); - $content_lines['title']['content'] = $this->escape_yaml($title); + $content_lines['title'] = array( + 'type' => 'string', + 'content' => $this->escape_yaml($title) + ); // Date (always included) $date = get_the_date('Y-m-d', $post); - $content_lines['date']['content'] = $date; + $content_lines['date'] = array( + 'type' => 'date', + 'content' => $date + ); // Author (always included) $author = get_the_author_meta('display_name', $post->post_author); - $content_lines['author']['content'] = $this->escape_yaml($author); + $content_lines['author'] = array( + 'type' => 'string', + 'content' => $this->escape_yaml($author) + ); // Featured image (only if set) $featured_image = get_the_post_thumbnail_url($post->ID, 'full'); if ($featured_image) { - $content_lines['featured_image']['content'] = $this->escape_yaml($featured_image); + $content_lines['featured_image'] = array( + 'type' => 'url', + 'content' => $this->escape_yaml($featured_image) + ); } // Taxonomies (categories and tags by default, but filterable) @@ -113,8 +125,14 @@ private function generate_frontmatter(WP_Post $post): string { $content_lines[$key]['items'] = array(); foreach ($terms as $term) { $content_lines[$key]['items'][] = array( - 'name' => $this->escape_yaml($term->name), - 'url' => $this->get_term_markdown_url($term), + 'name' => array( + 'type' => 'string', + 'content' => $this->escape_yaml($term->name) + ), + 'url' => array( + 'type' => 'url', + 'content' => $this->get_term_markdown_url($term) + ), ); } } @@ -127,15 +145,7 @@ private function generate_frontmatter(WP_Post $post): string { foreach ($content_lines as $key => $value) { // Single content line (like title, date, author, featured_image) if (isset($value['content'])) { - switch( $key ) { - case 'date': - $lines[] = $key . ': ' . $value['content']; - break; - default: - $lines[] = $key . ': "' . $value['content'] . '"'; - break; - - } + $lines[] = $key . ': ' . $this->format_yaml_value($value['content'], $value['type']); } // Multiple items (like categories and tags) if (isset($value['items']) && is_array($value['items'])) { @@ -144,11 +154,12 @@ private function generate_frontmatter(WP_Post $post): string { foreach ($value['items'] as $item) { $i = 0; foreach($item as $item_key => $item_value) { - $item[$item_key] = $this->escape_yaml($item_value); + // We should be also be looking into the item content type to add quotes only when needed, but for now we will just escape all item values and wrap them in quotes to be safe + $item_value = $this->format_yaml_value( $this->escape_yaml($item_value['content']), $item_value['type'] ); if ( $i === 0 ) { - $lines[] = ' - ' . $item_key . ': "' . $item[$item_key] . '"'; + $lines[] = ' - ' . $item_key . ': ' . $item_value; } else { - $lines[] = ' ' . $item_key . ': "' . $item[$item_key] . '"'; + $lines[] = ' ' . $item_key . ': ' . $item_value; } $i++; } @@ -165,6 +176,16 @@ private function generate_frontmatter(WP_Post $post): string { return implode("\n", $lines); } + private function format_yaml_value($value, $type) { + switch ($type) { + case 'date': + case 'number': + return $value; + default: + return '"' . $this->escape_yaml($value) . '"'; + } + } + /** * Get the markdown URL for a term (category or tag). * From aa9c7a57d9e0f8ae2f3ee46d85f2213f94ff9df5 Mon Sep 17 00:00:00 2001 From: Marco Almeida Date: Wed, 18 Feb 2026 14:21:24 +0000 Subject: [PATCH 5/6] PHP comment for the format_yaml_value method --- src/Output/ContentRenderer.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Output/ContentRenderer.php b/src/Output/ContentRenderer.php index 33429b1..7324bd8 100644 --- a/src/Output/ContentRenderer.php +++ b/src/Output/ContentRenderer.php @@ -176,6 +176,13 @@ private function generate_frontmatter(WP_Post $post): string { return implode("\n", $lines); } + /** + * Format a value for YAML output based on its type. + * + * @param string $value The value to format. + * @param string $type The type of the value (e.g. 'string', 'date', 'url', 'number'). + * @return string The formatted value for YAML. + */ private function format_yaml_value($value, $type) { switch ($type) { case 'date': From 16101be4438bd2cceee7c8ca1a709b372e5c020a Mon Sep 17 00:00:00 2001 From: Marco Almeida Date: Thu, 19 Feb 2026 08:52:43 +0000 Subject: [PATCH 6/6] Set type=array for multiple item lines, like taxonomies --- src/Output/ContentRenderer.php | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Output/ContentRenderer.php b/src/Output/ContentRenderer.php index 7324bd8..fd2d942 100644 --- a/src/Output/ContentRenderer.php +++ b/src/Output/ContentRenderer.php @@ -122,6 +122,7 @@ private function generate_frontmatter(WP_Post $post): string { foreach ($taxonomies as $taxonomy => $key) { $terms = get_the_terms($post->ID, $taxonomy); if ($terms && !is_wp_error($terms)) { + $content_lines[$key]['type'] = 'array'; $content_lines[$key]['items'] = array(); foreach ($terms as $term) { $content_lines[$key]['items'][] = array( @@ -138,24 +139,27 @@ private function generate_frontmatter(WP_Post $post): string { } } - // Allow 3rd party to modify content lines before they are added to the frontmatter + // Allow 3rd party to modify content lines before they are added to the raw lines $content_lines = apply_filters('markdown_alternate_frontmatter_content_lines', $content_lines, $post); // Add content lines to lines foreach ($content_lines as $key => $value) { - // Single content line (like title, date, author, featured_image) - if (isset($value['content'])) { - $lines[] = $key . ': ' . $this->format_yaml_value($value['content'], $value['type']); + if (!isset( $value['type']) || (empty($value['type']))) { + // Skip empty type values + continue; } - // Multiple items (like categories and tags) - if (isset($value['items']) && is_array($value['items'])) { + if ($value['type'] === 'array' && isset($value['items']) && is_array($value['items'])) { + // Multiple items (like categories and tags) $lines[] = $key . ':'; - $i = 0; foreach ($value['items'] as $item) { + //$item_lines = array(); $i = 0; - foreach($item as $item_key => $item_value) { - // We should be also be looking into the item content type to add quotes only when needed, but for now we will just escape all item values and wrap them in quotes to be safe - $item_value = $this->format_yaml_value( $this->escape_yaml($item_value['content']), $item_value['type'] ); + foreach ($item as $item_key => $item_value) { + if (!isset( $item_value['type']) || (empty($item_value['type'])) || (!isset( $item_value['content']))) { + // Skip empty type values or if content is not set + continue; + } + $item_value = $this->format_yaml_value($this->escape_yaml($item_value['content']), $item_value['type']); if ( $i === 0 ) { $lines[] = ' - ' . $item_key . ': ' . $item_value; } else { @@ -164,10 +168,13 @@ private function generate_frontmatter(WP_Post $post): string { $i++; } } + } elseif (isset($value['content'])) { + // Single content line (like title, date, author, featured_image) + $lines[] = $key . ': ' . $this->format_yaml_value($value['content'], $value['type']); } } - // Allow 3rd party to add lines + // Allow 3rd party to add lines before they're added to the frontmatter block (e.g. for custom fields or taxonomies that require a different structure) $lines = apply_filters('markdown_alternate_frontmatter_lines', $lines, $post); // YAML ender