定制 talleu/md-to-ooxml 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

talleu/md-to-ooxml

Composer 安装命令:

composer require talleu/md-to-ooxml

包简介

A lightweight PHP library to convert Markdown to Office Open XML (OOXML) and .docx files

README 文档

README

License: MIT

A lightweight, extensible PHP library to convert Markdown into Office Open XML (OOXML) — the XML format used inside Microsoft Word .docx files.

Use it to:

  • Generate .docx files directly from Markdown (with zero dependency on PHPWord or LibreOffice)
  • Get raw OOXML strings to embed into existing documents
  • Inject Markdown content into .docx templates

Features

Feature Built-in Parser CommonMark Adapter
Headings (H1–H6) with Word styles
Paragraphs & blank lines
Bold, italic, bold+italic
Underline
Strikethrough
Inline code
Fenced code blocks (with language)
Links
Images (text placeholder)
Bullet lists
Ordered lists
Blockquotes
Horizontal rules
Tables ✅ (requires table extension)
.docx file generation
Template injection

Requirements

  • PHP 8.3+
  • ext-zip (only required for .docx generation via DocxWriter)

Installation

composer require talleu/md-to-ooxml

Optional: CommonMark support

composer require league/commonmark

Quick Start

1. Markdown → OOXML string

use Talleu\MdToOoxml\OoXmlConverterFactory;

$converter = OoXmlConverterFactory::create();

// Full document XML (document.xml content)
$xml = $converter->convert('# Hello **World**');

// Body fragment only (no XML declaration / envelope)
$bodyXml = $converter->convertToBodyXml('# Hello **World**');

2. Markdown → .docx file

use Talleu\MdToOoxml\DocxWriter;

// One-liner: Markdown → .docx
DocxWriter::fromMarkdown('# My Document', '/path/to/output.docx');

// Or with a custom converter (e.g. CommonMark)
$converter = OoXmlConverterFactory::createWithCommonMark();
DocxWriter::fromMarkdown($markdown, '/path/to/output.docx', $converter);

3. Inject into an existing .docx template

use Talleu\MdToOoxml\DocxWriter;
use Talleu\MdToOoxml\OoXmlConverterFactory;

$converter = OoXmlConverterFactory::create();
$bodyXml = $converter->convertToBodyXml('## New Section');

// Append content before </w:body>
DocxWriter::injectIntoTemplate(
    templatePath: '/path/to/template.docx',
    bodyXml: $bodyXml,
    outputPath: '/path/to/output.docx',
);

// Or replace a placeholder string in the template
DocxWriter::injectIntoTemplate(
    templatePath: '/path/to/template.docx',
    bodyXml: $bodyXml,
    outputPath: '/path/to/output.docx',
    placeholder: '{{CONTENT}}',
);

4. Two-step: convert then save manually

use Talleu\MdToOoxml\OoXmlConverterFactory;
use Talleu\MdToOoxml\DocxWriter;

$converter = OoXmlConverterFactory::create();
$documentXml = $converter->convert($markdown);

// You can inspect/modify the XML here if needed
DocxWriter::save($documentXml, '/path/to/output.docx');

5. Render directly from an AST

If you already have a structured document (e.g. from your own parser, a CMS, or an API), you can skip the Markdown parsing step and pass an AST directly:

use Talleu\MdToOoxml\OoXmlConverterFactory;
use Talleu\MdToOoxml\Node\DocumentNode;
use Talleu\MdToOoxml\Node\ParagraphNode;
use Talleu\MdToOoxml\Node\TitleNode;
use Talleu\MdToOoxml\Node\TextRunNode;

$converter = OoXmlConverterFactory::create();

// Build the AST
$doc = new DocumentNode();

$title = new TitleNode(1);
$title->addChild(new TextRunNode('My Title'));
$doc->addChild($title);

$paragraph = new ParagraphNode();
$paragraph->addChild(new TextRunNode('Some text '));
$paragraph->addChild(new TextRunNode('in bold', isBold: true));
$doc->addChild($paragraph);

// Full document XML
$xml = $converter->renderDocument($doc);

// Or body fragment only
$bodyXml = $converter->renderToBodyXml($doc);

You can also get a standalone renderer without any parser dependency:

$renderer = OoXmlConverterFactory::createRenderer();
$xml = $renderer->render($doc);

See the Node Types table below for all available nodes and their properties.

Parsers

Built-in Parser (zero dependencies)

The default parser handles all common Markdown syntax via regex-based parsing. It's fast, lightweight, and requires no extra packages.

$converter = OoXmlConverterFactory::create();

Limitation: The built-in parser does not support nested inline formatting. For example, __some *italic* text__ will render the underline but treat the *italic* markers as literal text. If you need nested formatting (italic inside bold, underline inside strikethrough, etc.), use the CommonMark adapter below.

League CommonMark Adapter

For advanced Markdown features, use the adapter for league/commonmark:

$converter = OoXmlConverterFactory::createWithCommonMark();

The adapter automatically enables the Table and Strikethrough extensions if available.

Use the CommonMark adapter when you need:

  • Nested inline formatting (e.g. bold inside italic, italic inside underline)
  • Strict CommonMark compliance
  • Edge cases the built-in regex parser may not handle correctly

Custom Parser

Implement MarkdownParserInterface and inject it:

use Talleu\MdToOoxml\OoXmlConverterFactory;

$converter = OoXmlConverterFactory::createWithParser(new MyCustomParser());

Architecture

Markdown string
    │
    ▼
┌──────────────────┐
│  Parser           │  BlockParser (built-in) or LeagueCommonMarkAdapter
│  (Markdown → AST) │
└──────────────────┘
    │
    ▼
┌──────────────────┐
│  AST (Node tree)  │  DocumentNode → ParagraphNode → TextRunNode, etc.
└──────────────────┘
    │
    ▼
┌──────────────────┐
│  Renderer         │  NodeRenderer dispatches to per-node RendererInterface
│  (AST → OOXML)    │
└──────────────────┘
    │
    ▼
  OOXML string
    │
    ▼ (optional)
┌──────────────────┐
│  DocxWriter       │  Packages XML into a valid .docx ZIP archive
└──────────────────┘

Node Types

Node Description
DocumentNode Root node
ParagraphNode Paragraph
TitleNode Heading (level 1–6)
TextRunNode Inline text with formatting flags
InlineCodeNode Inline code span
LinkNode Hyperlink
ImageNode Image reference
ListItemNode Bullet or ordered list item
QuoteNode Blockquote
CodeBlockNode Fenced code block
BlankLineNode Empty line
HorizontalRuleNode Horizontal rule / thematic break
TableNode Table (contains TableRowNodeTableCellNode)

Extending

Register a custom renderer for any node type:

use Talleu\MdToOoxml\Renderer\NodeRenderer;
use Talleu\MdToOoxml\Renderer\RendererInterface;
use Talleu\MdToOoxml\Node\NodeInterface;

class MyCustomRenderer implements RendererInterface
{
    public function render(NodeInterface $node): string
    {
        // Return OOXML string
    }
}

// Get the factory-built converter and add your renderer
$converter = OoXmlConverterFactory::create();
// Or build the NodeRenderer manually for full control

Supported Markdown Syntax

# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6

Regular paragraph text.

**Bold text** and *italic text* and ***bold italic***.

__Underlined text__ and ~~strikethrough~~.

`inline code`

[Link text](https://example.com)

![Image alt](https://example.com/image.png)

- Bullet item
- Another item
* Also bullet
+ Also bullet

1. Ordered item
2. Another item

> Blockquote text

---

| Column A | Column B |
| -------- | -------- |
| Cell 1   | Cell 2   |

\```php
echo "fenced code block";
\```

Testing

# Run all tests
vendor/bin/phpunit

# Run only unit tests
vendor/bin/phpunit --testsuite Unit

# Run only integration tests
vendor/bin/phpunit --testsuite Integration

# Run only functional tests (requires ext-zip)
vendor/bin/phpunit --testsuite Functional

How It Works (OOXML Primer)

A .docx file is a ZIP archive containing XML files. The main one is word/document.xml. This library generates valid OOXML that follows the ECMA-376 specification.

The generated .docx includes:

File Purpose
[Content_Types].xml MIME type declarations
_rels/.rels Package-level relationships
word/document.xml The actual document content
word/_rels/document.xml.rels Document-level relationships
word/numbering.xml List (bullet/ordered) definitions
word/styles.xml Heading and default styles

License

MIT — see LICENSE.

talleu/md-to-ooxml 适用场景与选型建议

talleu/md-to-ooxml 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 13 次下载、GitHub Stars 达 8, 最近一次更新时间为 2026 年 03 月 31 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「xml」 「markdown」 「word」 「docx」 「converter」 「OOXML」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 talleu/md-to-ooxml 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 talleu/md-to-ooxml 我们能提供哪些服务?
定制开发 / 二次开发

基于 talleu/md-to-ooxml 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-31