phpsoftbox/markdown
Composer 安装命令:
composer require phpsoftbox/markdown
包简介
Safe Markdown renderer for PhpSoftBox documentation
README 文档
README
Компонент безопасного рендера Markdown-документов.
Пакет дает framework-level API поверх Markdown parser и YAML parser. Он умеет разбирать Markdown source, front matter, строить HTML, TOC, heading anchors, обрабатывать расширения синтаксиса и возвращать diagnostics без привязки к тому, где именно используется результат: в документации, админке, CMS, письмах или другом app-layer.
use PhpSoftBox\Markdown\MarkdownRenderer; $document = new MarkdownRenderer()->render(<<<'MD' --- title: Установка --- ## Быстрый старт Текст документации. MD); echo $document->html();
Возможности
- CommonMark/GFM Markdown;
- YAML front matter;
- deterministic
idу заголовков; MarkdownTocпо заданным уровням заголовков;- fenced code blocks с
languageиtitle="file.php"; - admonitions
note,tip,info,warning,danger; - tabs-блоки;
- backend-разбор MDX-lite component islands;
- diagnostics без падения рендера;
- resolver ссылок и assets;
- raw HTML disabled by default;
- блокировка опасных URL schemes.
Front Matter
--- title: Установка slug: /quick-start/installation sidebar_position: 10 draft: false --- # Установка
$document = $renderer->render($source); $document->frontMatter(); // ['title' => 'Установка', ...]
Если YAML невалидный, компонент вернет diagnostic front_matter.invalid, но тело
документа останется доступным.
TOC И Anchors
Заголовки получают стабильные id:
## Install ## Install
Результат:
<h2 id="install">Install</h2> <h2 id="install-2">Install</h2>
Диапазон TOC настраивается:
use PhpSoftBox\Markdown\MarkdownRenderOptions; $document = $renderer->render($source, new MarkdownRenderOptions( tocMinHeadingLevel: 2, tocMaxHeadingLevel: 3, ));
Links И Assets
Renderer не знает файловую структуру, правила роутинга и публичные URL приложения. Для этого передается resolver:
use PhpSoftBox\Markdown\Contracts\MarkdownLinkResolverInterface; use PhpSoftBox\Markdown\MarkdownRenderContext; use PhpSoftBox\Markdown\MarkdownResolvedAsset; use PhpSoftBox\Markdown\MarkdownResolvedLink; final class AppMarkdownLinkResolver implements MarkdownLinkResolverInterface { public function resolveLink(string $target, MarkdownRenderContext $context): MarkdownResolvedLink { return MarkdownResolvedLink::resolved('/content/' . trim($target, './')); } public function resolveAsset(string $target, MarkdownRenderContext $context): MarkdownResolvedAsset { return MarkdownResolvedAsset::resolved('/assets/content/' . trim($target, './')); } }
$document = $renderer->render($source, new MarkdownRenderOptions( basePath: '/content', currentDocumentPath: 'articles/install.md', linkResolver: new AppMarkdownLinkResolver(), ));
Если resolver не смог найти цель, он возвращает MarkdownResolvedLink::unresolved()
или MarkdownResolvedAsset::unresolved(). Renderer добавит diagnostics
link.unresolved или asset.unresolved.
Code Blocks
Поддерживается title в info string:
```php title="src/Action.php" echo 'ok'; ```
В HTML появятся data-language, data-title и подпись блока.
Если задан allowedCodeLanguages, неизвестный язык попадет в diagnostic
code.language_unknown.
Admonitions
:::warning Перед деплоем проверьте переменные окружения. :::
Поддержанные типы:
note;tip;info;warning;danger.
Неизвестный тип возвращает diagnostic admonition.unknown.
Tabs
Tabs-блок задается контейнером :::tabs и секциями @tab:
:::tabs @tab PHP ```php echo 'ok'; ``` @tab JavaScript ```js console.log('ok'); ``` :::
Renderer вернет статичный HTML:
<div class="markdown-tabs"> <div class="markdown-tabs__nav" role="tablist">...</div> <div class="markdown-tabs__panels">...</div> </div>
Компонент не навязывает JS-поведение. Приложение может подключить собственный
скрипт/React-компонент поверх классов markdown-tabs* и data-tab.
Некорректный блок возвращает diagnostic tabs.invalid.
MDX-Lite Components
Компонент не выполняет JSX и не компилирует настоящий MDX. Backend-часть поддерживает безопасные component islands: renderer распознает whitelisted компоненты, валидирует props через resolver и возвращает HTML-placeholder для будущего фронтового registry/hydration.
Поддержанный синтаксис:
<Alert type="warning" count={3} enabled> **Важно:** проверьте настройки. </Alert> <Icon name="check" />
Поддержанные props:
- строки:
type="warning"илиtype='warning'; - boolean shorthand:
enabled; - простые литералы:
{true},{false},{null},{3},{3.14}.
Произвольные JS expressions не выполняются и возвращают diagnostic
mdx.props_invalid.
Resolver задает список разрешенных компонентов и может нормализовать props:
use PhpSoftBox\Markdown\Contracts\MarkdownComponentResolverInterface; use PhpSoftBox\Markdown\MarkdownRenderContext; use PhpSoftBox\Markdown\MarkdownResolvedComponent; final class AppMarkdownComponentResolver implements MarkdownComponentResolverInterface { public function resolveComponent( string $name, array $props, string $content, MarkdownRenderContext $context, ): MarkdownResolvedComponent { return match ($name) { 'Alert' => MarkdownResolvedComponent::resolved('Alert', $props), 'Icon' => MarkdownResolvedComponent::resolved('Icon', $props), default => MarkdownResolvedComponent::unresolved($name), }; } }
$document = $renderer->render($source, new MarkdownRenderOptions( componentResolver: new AppMarkdownComponentResolver(), )); $document->components();
HTML-placeholder выглядит так:
<div class="markdown-component markdown-component--alert" data-mdx-component="Alert" data-mdx-props='{"type":"warning","enabled":true}' data-mdx-resolved="true" > <p><strong>Важно:</strong> проверьте настройки.</p> </div>
React/Vue/другой frontend-layer может позже подключить свой registry компонентов
поверх data-mdx-component и data-mdx-props. Backend при этом уже отдает fallback
HTML, metadata и diagnostics.
Ограничения backend MVP:
- только block-level компоненты;
- без
import/export; - без JSX expressions;
- без inline components внутри строки;
- без выполнения JavaScript.
HTML Safety
По умолчанию raw HTML экранируется:
use PhpSoftBox\Markdown\MarkdownHtmlPolicy; use PhpSoftBox\Markdown\MarkdownRenderOptions; $document = $renderer->render($source, new MarkdownRenderOptions( htmlPolicy: MarkdownHtmlPolicy::Escape, ));
Доступные политики:
MarkdownHtmlPolicy::Escape;MarkdownHtmlPolicy::Strip;MarkdownHtmlPolicy::Allow.
Даже при разрешенном HTML renderer блокирует опасные URL schemes:
javascript:, vbscript:, data:.
Для внешних ссылок можно включить target/rel:
$document = $renderer->render($source, new MarkdownRenderOptions( externalLinkTarget: '_blank', externalLinksNoFollow: true, ));
Diagnostics
Минимальные коды:
front_matter.invalid;link.unresolved;asset.unresolved;html.disallowed;admonition.unknown;tabs.invalid;mdx.component_unknown;mdx.syntax_invalid;mdx.props_invalid;heading.duplicate_id;code.language_unknown.
foreach ($document->diagnostics() as $diagnostic) { echo $diagnostic->code() . ': ' . $diagnostic->message(); }
Лицензия
MIT
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-26