Как разобрать Markdown в PHP?

Во-первых, я знаю, что уже есть анализатор Markdown для PHP. Я также посмотрел на этот вопрос, но он не отвечает на мой вопрос.

Очевидно, что даже если в названии упоминается PHP, если он не зависит от языка, потому что я хотел бы знать, какой шаг я должен пройти, чтобы сделать это.

Я читал о PEG, но должен признать, что я не совсем понял пример, предоставленный с парсером PHP.

Я также читал о CFG.

Я обнаружил Zend_Markup_Parser_Textile, который, кажется, создает так называемое "дерево токенов" (как насчет этого?), Но в настоящее время его невозможно использовать. (Кстати, текстиль не уценка)

Так, конкретно, как бы вы пошли на это?

Очевидно, я думал об использовании Regex, но, боюсь.

Потому что Markdown поддерживает несколько синтаксисов для одного и того же элемента (Setext и atx).

Не могли бы вы дать отправную точку?

4 ответа

Вы должны взглянуть на Parsedown.

Он анализирует текст Markdown, как это делают люди. Во-первых, он делит тексты на строки. Затем рассматривается, как эти строки начинаются и связаны друг с другом. Наконец, он ищет специальные символы для идентификации встроенных элементов.

Существует PHP Markdown Extra, который кажется популярным, вы можете начать с его источника.

Также есть объектно-ориентированная реализация Markdown, которая работает быстрее: markdown-oo-php

Ciconia - я нашел новый анализатор Markdown для PHP.

Вам просто нужно сделать 3 вещи:

1.Установите Ciconia и проанализируйте файл в соответствии с документом.
2. Добавьте соответствующую тему CSS, чтобы сделать ее красивой, например, стиль разметки github или здесь.
3. Добавьте подсветку синтаксиса javascript, например, префиксатор кода JavaScript для Google.

Тогда все будет выглядеть довольно хорошо.

Если вам нужен полный пример, вот мое рабочее демо для разметки в стиле github:

<?php
header("Content-Type: text/html;charset=utf-8");
require 'vendor/autoload.php';
use Ciconia\Ciconia;
use Ciconia\Extension\Gfm;

$ciconia = new Ciconia();
$ciconia->addExtension(new Gfm\FencedCodeBlockExtension());
$ciconia->addExtension(new Gfm\TaskListExtension());
$ciconia->addExtension(new Gfm\InlineStyleExtension());
$ciconia->addExtension(new Gfm\WhiteSpaceExtension());
$ciconia->addExtension(new Gfm\TableExtension());
$ciconia->addExtension(new Gfm\UrlAutoLinkExtension());
$contents = file_get_contents('Readme.md');
$html = $ciconia->render($contents);
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Excel to Lua table - Readme</title>
        <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
        <link rel="stylesheet" href="./github-markdown.css">
        <style>
            .markdown-body {
                box-sizing: border-box;
                min-width: 200px;
                max-width: 980px;
                margin: 0 auto;
                padding: 45px;
            }
        </style>
    </head>
    <body>
        <article class="markdown-body">
        <?php
            # Put HTML content in the document
            echo $html;
        ?>
        </article>
    </body>
</html>

Использование регулярных выражений.

<?php

/**
 * Slimdown - A very basic regex-based Markdown parser. Supports the
 * following elements (and can be extended via Slimdown::add_rule()):
 *
 * - Headers
 * - Links
 * - Bold
 * - Emphasis
 * - Deletions
 * - Quotes
 * - Inline code
 * - Blockquotes
 * - Ordered/unordered lists
 * - Horizontal rules
 *
 * Author: Johnny Broadway <johnny@johnnybroadway.com>
 * Website: https://gist.github.com/jbroadway/2836900
 * License: MIT
 */
class Slimdown {
    public static $rules = array (
        '/(#+)(.*)/' => 'self::header',                           // headers
        '/\[([^\[]+)\]\(([^\)]+)\)/' => '<a href=\'\2\'>\1</a>',  // links
        '/(\*\*|__)(.*?)\1/' => '<strong>\2</strong>',            // bold
        '/(\*|_)(.*?)\1/' => '<em>\2</em>',                       // emphasis
        '/\~\~(.*?)\~\~/' => '<del>\1</del>',                     // del
        '/\:\"(.*?)\"\:/' => '<q>\1</q>',                         // quote
        '/`(.*?)`/' => '<code>\1</code>',                         // inline code
        '/\n\*(.*)/' => 'self::ul_list',                          // ul lists
        '/\n[0-9]+\.(.*)/' => 'self::ol_list',                    // ol lists
        '/\n(&gt;|\>)(.*)/' => 'self::blockquote ',               // blockquotes
        '/\n-{5,}/' => "\n<hr />",                                // horizontal rule
        '/\n([^\n]+)\n/' => 'self::para',                         // add paragraphs
        '/<\/ul>\s?<ul>/' => '',                                  // fix extra ul
        '/<\/ol>\s?<ol>/' => '',                                  // fix extra ol
        '/<\/blockquote><blockquote>/' => "\n"                    // fix extra blockquote
    );

    private static function para ($regs) {
        $line = $regs[1];
        $trimmed = trim ($line);
        if (preg_match ('/^<\/?(ul|ol|li|h|p|bl)/', $trimmed)) {
            return "\n" . $line . "\n";
        }
        return sprintf ("\n<p>%s</p>\n", $trimmed);
    }

    private static function ul_list ($regs) {
        $item = $regs[1];
        return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim ($item));
    }

    private static function ol_list ($regs) {
        $item = $regs[1];
        return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim ($item));
    }

    private static function blockquote ($regs) {
        $item = $regs[2];
        return sprintf ("\n<blockquote>%s</blockquote>", trim ($item));
    }

    private static function header ($regs) {
        list ($tmp, $chars, $header) = $regs;
        $level = strlen ($chars);
        return sprintf ('<h%d>%s</h%d>', $level, trim ($header), $level);
    }

    /**
     * Add a rule.
     */
    public static function add_rule ($regex, $replacement) {
        self::$rules[$regex] = $replacement;
    }

    /**
     * Render some Markdown into HTML.
     */
    public static function render ($text) {
        $text = "\n" . $text . "\n";
        foreach (self::$rules as $regex => $replacement) {
            if (is_callable ( $replacement)) {
                $text = preg_replace_callback ($regex, $replacement, $text);
            } else {
                $text = preg_replace ($regex, $replacement, $text);
            }
        }
        return trim ($text);
    }
}


echo Slimdown::render ("# Title

And *now* [a link](http://www.google.com) to **follow** and [another](http://yahoo.com/).

* One
* Two
* Three

## Subhead

One **two** three **four** five.

One __two__ three _four_ five __six__ seven _eight_.

1. One
2. Two
3. Three

More text with `inline($code)` sample.

> A block quote
> across two lines.

More text...");

Тест https://3v4l.org/6JlAI

Источник https://gist.github.com/jbroadway/2836900

Другие вопросы по тегам