Problem/Motivation

The main problem statement was raised in #3548981-4: Output markdown menu links when Markdownify is enabled.

Currently, appending .md to URLs only works for content that is explicitly configured for markdown conversion in Markdownify module settings. This creates inconsistent behavior where some URLs with .md suffixes work while others fail, particularly when:

  • Views pages are accessed with .md suffix but the Markdownify Views submodule is not enabled
  • Content types that aren't configured for markdown conversion are requested
  • Administrative or form pages are accessed with .md suffix

The core issue is that there's no fallback mechanism to convert any HTML output to markdown when the specialized conversion methods aren't available.

Steps to reproduce

  1. Install Markdownify module with basic configuration
  2. Enable markdown conversion for nodes only (not Views)
  3. Visit any Views page URL and append .md (e.g., /admin/content.md)
  4. Observe the request fails or returns non-markdown content
  5. Try accessing a taxonomy term page with .md suffix when taxonomy markdown conversion is not configured

Proposed resolution

Create a Proof of Concept (POC) implementation using a custom MainContentRendererInterface that can convert any HTML output to markdown as a universal fallback mechanism.

Implementation Approach

NOTE: AI generated!!!

1. Custom Main Content Renderer Service

Register a new service main_content_renderer.markdown that implements MainContentRendererInterface:

# markdownify.services.yml
services:
  main_content_renderer.markdown:
    class: Drupal\markdownify\Render\MainContent\MarkdownRenderer
    arguments:
      - '@renderer'
      - '@html_to_markdown.converter'
      - '@markdownify.content_converter'
    tags:
      - { name: render.main_content_renderer, format: markdown }

2. Markdown Renderer Implementation

<?php

namespace Drupal\markdownify\Render\MainContent;

use Drupal\Core\Render\MainContent\MainContentRendererInterface;
use Drupal\Core\Render\RendererInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Routing\RouteMatchInterface;

class MarkdownRenderer implements MainContentRendererInterface {
  
  public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match) {
    // 1. Check if specialized markdown conversion is available
    if ($this->hasSpecializedConverter($main_content, $route_match)) {
      return $this->renderSpecialized($main_content, $request, $route_match);
    }
    
    // 2. Fallback: Render as HTML first, then convert to markdown
    $html_output = $this->renderer->renderPlain($main_content);
    $markdown_content = $this->convertHtmlToMarkdown($html_output);
    
    $response = new Response($markdown_content);
    $response->headers->set('Content-Type', 'text/markdown; charset=UTF-8');
    
    return $response;
  }
}

3. URL Handling Integration

Modify the routing system to recognize .md suffixes and set the appropriate wrapper format in a RouteSubscriber or middleware

POC Scope and Limitations

What the POC will test:

  • Universal HTML-to-markdown conversion capability - but when there is a optimal conversation method, meaning the existing ones, that should be preferred.
  • Integration with existing Markdownify conversion methods
  • Performance impact of the fallback approach
  • Compatibility with different content types and Views

Known limitations to document:

  • Forms and AJAX: Interactive elements cannot be meaningfully converted to markdown
  • Administrative interfaces: Admin pages should be excluded from markdown conversion
  • Content fidelity: Some HTML structures may not convert cleanly to markdown
  • Caching considerations: Markdown responses MAY need separate cache handling

Areas requiring further investigation:

  • Cache strategy for converted content
  • Error handling for conversion failures
  • Integration with existing Markdownify configuration

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Comments

mxr576 created an issue.

mxr576’s picture