Fix broken markdown URL for static front page#6
Fix broken markdown URL for static front page#6TBarregren wants to merge 1 commit intoProgressPlanner:mainfrom
Conversation
When a static page is set as the front page, get_permalink() returns the site root URL (e.g. https://example.com/). The existing code strips the trailing slash and appends .md, producing an invalid URL like https://example.com.md. This fix detects the front page case and uses /index.md instead. The slug is filterable via 'markdown_alternate_front_page_slug'. Affected locations: - AlternateLinkHandler: <link rel="alternate"> tag generation - RewriteHandler: Accept header content negotiation redirect - RewriteHandler: REQUEST_URI parsing for /index.md routing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@ilicfilip could you see if this or #8 is the better approach? |
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where static front pages produce invalid markdown URLs (e.g., https://example.com.md instead of https://example.com/index.md). The issue occurs because get_permalink() returns the site root URL for the front page, and appending .md after stripping the trailing slash creates a malformed URL.
Changes:
- Added front page detection logic using URL comparison in three locations
- Introduced a new filterable slug
markdown_alternate_front_page_slug(default: "index") for the front page markdown URL - Extracted URL building logic into a private method in
AlternateLinkHandler
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| src/Discovery/AlternateLinkHandler.php | Added build_markdown_url() method to detect front pages and generate appropriate markdown URLs |
| src/Router/RewriteHandler.php | Added front page detection in parse_markdown_url() to route /index.md to the front page, and in handle_accept_negotiation() to generate correct redirect URLs |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Build markdown URL — detect front page to avoid invalid domain.md URL. | ||
| $site_url = trailingslashit(home_url()); | ||
| if (trailingslashit($canonical) === $site_url) { | ||
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); |
There was a problem hiding this comment.
The coding style here is inconsistent with the rest of the RewriteHandler.php file. This file uses no spaces inside function call parentheses (e.g., line 157: apply_filters('markdown_alternate_supported_post_types', $default_types)), but this line has spaces. For consistency with the existing code in this file, this should be apply_filters('markdown_alternate_front_page_slug', 'index') without spaces.
| $slug = $matches[1]; | ||
|
|
||
| // Check if this is the front page slug (default "index", filterable). | ||
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); |
There was a problem hiding this comment.
The filter output should be sanitized before use to prevent potential security issues. Consider using sanitize_title() or at minimum validating that the slug contains only safe URL characters. This prevents malicious or malformed slugs from being used in URL construction, even though the impact is limited since WordPress will ultimately handle the URL.
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); | |
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); | |
| // Ensure the filtered slug is safe before using it in routing logic. | |
| if (!is_string($front_slug)) { | |
| $front_slug = 'index'; | |
| } elseif (!preg_match('/^[A-Za-z0-9\-._~\/]+$/', $front_slug)) { | |
| // Fallback to a safe default if the slug contains unexpected characters. | |
| $front_slug = 'index'; | |
| } |
| // Detect if this is the static front page by comparing to site URL. | ||
| $site_url = trailingslashit( home_url() ); | ||
| if ( trailingslashit( $permalink ) === $site_url ) { |
There was a problem hiding this comment.
Consider using a more direct approach to detect the front page by comparing post IDs instead of URLs. This would be more reliable and clearer. For example: if ((int) get_option('page_on_front') === $post->ID && get_option('show_on_front') === 'page'). This approach avoids potential edge cases with URL formatting and is more explicit about checking the WordPress front page setting.
| // Detect if this is the static front page by comparing to site URL. | |
| $site_url = trailingslashit( home_url() ); | |
| if ( trailingslashit( $permalink ) === $site_url ) { | |
| // Detect if this is the static front page using WordPress front page settings. | |
| $is_static_front_page = ( | |
| get_option( 'show_on_front' ) === 'page' | |
| && (int) get_option( 'page_on_front' ) === (int) $post->ID | |
| ); | |
| if ( $is_static_front_page ) { | |
| $site_url = trailingslashit( home_url() ); |
| // Build markdown URL — detect front page to avoid invalid domain.md URL. | ||
| $site_url = trailingslashit(home_url()); | ||
| if (trailingslashit($canonical) === $site_url) { | ||
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); | ||
| $md_url = $site_url . $front_slug . '.md'; | ||
| } else { | ||
| $md_url = rtrim($canonical, '/') . '.md'; | ||
| } |
There was a problem hiding this comment.
Consider using a more direct approach to detect the front page. Since this code runs during template_redirect (when WordPress query is available), you could use is_front_page() to check if the current page is the front page, which would be clearer and more reliable than URL comparison. This would also be consistent with WordPress conventions for front page detection.
| // Detect if this is the static front page by comparing to site URL. | ||
| $site_url = trailingslashit( home_url() ); | ||
| if ( trailingslashit( $permalink ) === $site_url ) { | ||
| $front_slug = apply_filters( 'markdown_alternate_front_page_slug', 'index' ); |
There was a problem hiding this comment.
The filter output should be sanitized before use in URL construction. Consider using sanitize_title() to ensure the slug contains only safe URL characters. This prevents potential security issues from malicious filter values and ensures the generated URL is well-formed.
| $front_slug = apply_filters( 'markdown_alternate_front_page_slug', 'index' ); | |
| $front_slug = apply_filters( 'markdown_alternate_front_page_slug', 'index' ); | |
| $front_slug = sanitize_title( (string) $front_slug ); | |
| if ( $front_slug === '' ) { | |
| $front_slug = 'index'; | |
| } |
| // Build markdown URL — detect front page to avoid invalid domain.md URL. | ||
| $site_url = trailingslashit(home_url()); | ||
| if (trailingslashit($canonical) === $site_url) { | ||
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); |
There was a problem hiding this comment.
The filter output should be sanitized before use in URL construction. Consider using sanitize_title() to ensure the slug contains only safe URL characters. This prevents potential security issues from malicious filter values and ensures the generated URL is well-formed.
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); | |
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); | |
| $front_slug = sanitize_title($front_slug); |
| $slug = $matches[1]; | ||
|
|
||
| // Check if this is the front page slug (default "index", filterable). | ||
| $front_slug = apply_filters('markdown_alternate_front_page_slug', 'index'); |
There was a problem hiding this comment.
The coding style here is inconsistent with the rest of the RewriteHandler.php file. This file uses no spaces inside function call parentheses (e.g., line 157: apply_filters('markdown_alternate_supported_post_types', $default_types)), but this line has spaces. For consistency with the existing code in this file, this should be apply_filters('markdown_alternate_front_page_slug', 'index') without spaces.
|
Thanks for this fix — this appears superseded by #8 (same static front-page markdown URL area) and is currently conflicting with main. Closing to reduce overlap and keep one active path for this fix. |
Summary
Fixes #5.
get_permalink()returns the site root URL (e.g.https://example.com/). The existingrtrim('/') . '.md'logic produces an invalid URL likehttps://example.com.md./index.mdinstead. The slug is filterable via a newmarkdown_alternate_front_page_slugfilter (default:"index").AlternateLinkHandler::output_alternate_link(),RewriteHandler::handle_accept_negotiation(), andRewriteHandler::parse_markdown_url().Test plan
<head>— verify the<link rel="alternate">points to/index.md(notexample.com.md)/index.mddirectly — verify it serves the front page as markdownAccept: text/markdownto the front page — verify it redirects to/index.md.mdURLs for regular posts/pages still workmarkdown_alternate_front_page_slugfilter to change "index" to e.g. "home"🤖 Generated with Claude Code