{"record":{"id":"5dae0c8a693d332a","repo":"twigphp/Twig","slug":"you-cannot-use-the-html-to-markdown-filter-as-league-html-to","errorCode":null,"errorMessage":"You cannot use the \"html_to_markdown\" filter as league/html-to-markdown is not installed; try running \"composer require league/html-to-markdown\".","messagePattern":"You cannot use the \"html_to_markdown\" filter as league/html-to-markdown is not installed; try running \"composer require league/html-to-markdown\"\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"extra/markdown-extra/MarkdownExtension.php","lineNumber":36,"sourceCode":"final class MarkdownExtension extends AbstractExtension\n{\n    public function getFilters(): array\n    {\n        return [\n            new TwigFilter('markdown_to_html', ['Twig\\\\Extra\\\\Markdown\\\\MarkdownRuntime', 'convert'], ['is_safe' => ['html']]),\n            new TwigFilter('html_to_markdown', [self::class, 'htmlToMarkdown']),\n        ];\n    }\n\n    /**\n     * @internal\n     */\n    public static function htmlToMarkdown(string $body, array $options = []): string\n    {\n        static $converters;\n\n        if (!class_exists(HtmlConverter::class)) {\n            throw new \\LogicException('You cannot use the \"html_to_markdown\" filter as league/html-to-markdown is not installed; try running \"composer require league/html-to-markdown\".');\n        }\n\n        $options += [\n            'hard_break' => true,\n            'strip_tags' => true,\n            'remove_nodes' => 'head style',\n        ];\n\n        if (!isset($converters[$key = serialize($options)])) {\n            $converters[$key] = new HtmlConverter($options);\n        }\n\n        return $converters[$key]->convert($body);\n    }\n}\n","sourceCodeStart":18,"sourceCodeEnd":52,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/extra/markdown-extra/MarkdownExtension.php#L18-L52","documentation":"MarkdownExtension::htmlToMarkdown() is a static helper backing the html_to_markdown filter. It requires league/html-to-markdown's HtmlConverter class; if that package is not installed it throws a LogicException telling you to composer require it. Unlike the markdown_to_html side, no alternative library is accepted.","triggerScenarios":"Using the {{ content|html_to_markdown }} filter (or calling MarkdownExtension::htmlToMarkdown directly, as tests do) in a project where league/html-to-markdown is absent.","commonSituations":"Installing twig/markdown-extra without league/html-to-markdown (they are separate optional packages); forgetting the dep in a production composer.json while present locally via require-dev; CI environments with --no-dev installs.","solutions":["Run \"composer require league/html-to-markdown\".","Guard usage: check class_exists(\\League\\HTMLToMarkdown\\HtmlConverter::class) before enabling the filter in your extension config."],"exampleFix":"// before\n{{ body|html_to_markdown }}\n// after (after running: composer require league/html-to-markdown)\n{{ body|html_to_markdown }}","handlingStrategy":"validation","validationCode":"if (!class_exists(\\League\\HTMLToMarkdown\\HtmlConverter::class)) {\n    // skip registering/enabling the html_to_markdown filter or fail fast with install instructions\n}","typeGuard":null,"tryCatchPattern":"try {\n    $md = \\Twig\\Extra\\Markdown\\MarkdownExtension::htmlToMarkdown($html);\n} catch (\\LogicException $e) {\n    // league/html-to-markdown not installed; degrade gracefully\n}","preventionTips":["Add league/html-to-markdown to composer.json's require section (not require-dev) if any template uses html_to_markdown.","Check class_exists(\\League\\HTMLToMarkdown\\HtmlConverter::class) in a health check or feature-flag setup.","Note that league/commonmark alone is NOT sufficient for html_to_markdown — the two filters need different packages."],"tags":["php","composer","markdown","missing-package","twig-filter"],"backgroundTag":"missing-optional-dependency","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}