soleinjast/symfony-markdown-response-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

soleinjast/symfony-markdown-response-bundle

Composer 安装命令:

composer require soleinjast/symfony-markdown-response-bundle

包简介

Serve markdown versions of your HTML pages to AI agents and bots

README 文档

README

Symfony Markdown Response Bundle

Latest Stable Version Total Downloads PHP Symfony License: MIT

Introduction

A Symfony bundle that automatically serves Markdown versions of your HTML pages to AI agents, bots, and any client that requests it. Controllers opt in with a single PHP attribute — the bundle handles detection, conversion, and caching transparently.

Why

AI assistants (ChatGPT, Claude, Perplexity, etc.) and autonomous agents consume web content better as plain Markdown than as HTML. Stripping navigation, scripts, styles, and markup noise reduces token usage and improves comprehension — without maintaining a separate content pipeline.

Installation

composer require soleinjast/symfony-markdown-response-bundle

If you are not using Symfony Flex, register the bundle manually:

// config/bundles.php
return [
    // ...
    Soleinjast\SymfonyMarkdownResponseBundle\SymfonyMarkdownResponseBundle::class => ['all' => true],
];

Quick Start

1. Opt a controller in

Apply the #[ProvideMarkdownResponse] attribute to a controller class or to individual action methods.

use Soleinjast\SymfonyMarkdownResponseBundle\Attribute\ProvideMarkdownResponse;

#[ProvideMarkdownResponse]
class DocsController extends AbstractController
{
    public function index(): Response { /* ... */ }
    public function show(): Response  { /* ... */ }
}

Or enable it per-method and disable it on specific actions:

#[ProvideMarkdownResponse]
class BlogController extends AbstractController
{
    public function index(): Response { /* ... */ }

    #[ProvideMarkdownResponse(enabled: false)]
    public function edit(): Response { /* only humans edit posts */ }
}

2. That's it

The bundle detects AI clients automatically. No changes to routes, templates, or responses are required.

How Detection Works

A request is considered to want Markdown if any of the following is true:

Signal Example
Accept: text/markdown header Accept: text/markdown, */*
.md URL suffix GET /docs/setup.md
Known AI User-Agent substring User-Agent: GPTBot/1.0
_wants_markdown request attribute Set internally after .md rewrite

The .md suffix is stripped before routing so your route definitions remain unchanged. The _wants_markdown attribute is set on the request to carry the intent forward to the response phase.

Default User-Agent patterns:

GPTBot, ChatGPT-User, CCBot, anthropic-ai, Claude-Web, ClaudeBot, PerplexityBot

Configuration

Publish the configuration file (optional — all keys have defaults):

# config/packages/symfony_markdown_response.yaml
symfony_markdown_response:
    driver: local               # "local" or "cloudflare"
    cloudflare_endpoint: ~      # required when driver is "cloudflare"
    cache_enabled: true
    cache_ttl: 3600             # seconds
    cache_service: ~            # PSR-6 service ID; defaults to cache.app
    ai_user_agents:
        - GPTBot
        - ChatGPT-User
        - CCBot
        - anthropic-ai
        - Claude-Web
        - ClaudeBot
        - PerplexityBot

Configuration reference

Key Type Default Description
driver local|cloudflare local Conversion backend
cloudflare_endpoint string|null null Cloudflare Workers AI URL (required for cloudflare driver)
cache_enabled bool true Cache converted Markdown
cache_ttl int 3600 Cache TTL in seconds
cache_service string|null null PSR-6 cache pool service ID; falls back to cache.app then cache.system
ai_user_agents string[] (see above) User-Agent substrings that trigger Markdown responses

Conversion Drivers

local (default)

Uses league/html-to-markdown. Conversion happens in-process with no external dependencies. The following HTML nodes are stripped before conversion: head, script, style, nav, footer, aside.

cloudflare

Posts the HTML to a Cloudflare Workers AI endpoint and returns the response body as Markdown. Requires symfony/http-client and a configured endpoint URL.

symfony_markdown_response:
    driver: cloudflare
    cloudflare_endpoint: 'https://your-worker.example.workers.dev/to-markdown'

Caching

Converted Markdown is cached by default using a PSR-6 cache pool. The cache key is derived from an xxh3 hash of the pre-processed HTML, so distinct page content produces distinct cache entries.

Resolution order for the cache pool:

  1. cache_service if explicitly configured
  2. cache.app if present in the container
  3. cache.system if present in the container
  4. No caching (conversion runs on every request)

To disable caching entirely:

symfony_markdown_response:
    cache_enabled: false

Preprocessing Pipeline

You can strip or transform HTML before conversion by implementing HtmlPreprocessorInterface. Services implementing this interface are auto-configured via the symfony_markdown_response.html_preprocessor tag.

use Soleinjast\SymfonyMarkdownResponseBundle\Converter\HtmlPreprocessorInterface;

class RemoveCookieBannerPreprocessor implements HtmlPreprocessorInterface
{
    public function process(string $html): string
    {
        // Remove cookie consent banners, ads, or any other noise
        return preg_replace('/<div[^>]+class="[^"]*cookie[^"]*".*?<\/div>/si', '', $html);
    }
}

Register it as a service (or rely on autowiring/autoconfiguration):

# config/services.yaml
App\Preprocessor\RemoveCookieBannerPreprocessor:
    tags:
        - { name: symfony_markdown_response.html_preprocessor }

Multiple preprocessors are applied in the order they are resolved from the container.

Accessing Markdown Programmatically

The MarkdownConverter service is available for injection if you need to convert HTML outside of the HTTP cycle:

use Soleinjast\SymfonyMarkdownResponseBundle\Converter\MarkdownConverter;

class SitemapExporter
{
    public function __construct(private readonly MarkdownConverter $converter) {}

    public function export(string $html): string
    {
        return $this->converter->convert($html);
    }
}

Requesting Markdown as a Client

There are three ways to request a Markdown response:

1. URL suffix

GET /docs/getting-started.md HTTP/1.1

2. Accept header

GET /docs/getting-started HTTP/1.1
Accept: text/markdown

3. Known AI User-Agent (automatic — no client changes required)

GET /docs/getting-started HTTP/1.1
User-Agent: GPTBot/1.0

All three methods produce a response with Content-Type: text/markdown; charset=UTF-8.

Contributing

Contributions are welcome. Please open an issue before submitting a pull request for significant changes so the approach can be discussed first.

  1. Fork the repository
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Write tests for your changes
  4. Submit a pull request

License

Released under the MIT License.

Happy coding! 🎉

统计信息

  • 总下载量: 409
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 8
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 7
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-20

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固