phpsoftbox/markdown 问题修复 & 功能扩展

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

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

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
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-26

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固