开源软件名称(OpenSource Name):cebe/markdown开源软件地址(OpenSource Url):https://github.com/cebe/markdown开源编程语言(OpenSource Language):HTML 63.7%开源软件介绍(OpenSource Introduction):A super fast, highly extensible markdown parser for PHPWhat is this?A set of PHP classes, each representing a Markdown flavor, and a command line tool for converting markdown files to HTML files. The implementation focus is to be fast (see benchmark) and extensible. Parsing Markdown to HTML is as simple as calling a single method (see Usage) providing a solid implementation that gives most expected results even in non-trivial edge cases. Extending the Markdown language with new elements is as simple as adding a new method to the class that converts the markdown text to the expected output in HTML. This is possible without dealing with complex and error prone regular expressions. It is also possible to hook into the markdown structure and add elements or read meta information using the internal representation of the Markdown text as an abstract syntax tree (see Extending the language). Currently the following markdown flavors are supported:
Future plans are to support:
Who is using it?
InstallationPHP 5.4 or higher is required to use it. It will also run on facebook's hhvm. The library uses PHPDoc annotations to determine the markdown elements that should be parsed.
So in case you are using PHP Installation is recommended to be done via composer by running:
Alternatively you can add the following to the "cebe/markdown": "~1.2.0" Run
UsageIn your PHP projectTo parse your markdown you need only two lines of code. The first one is to choose the markdown flavor as one of the following:
The next step is to call the Here are some examples: // traditional markdown and parse full text
$parser = new \cebe\markdown\Markdown();
echo $parser->parse($markdown);
// use github markdown
$parser = new \cebe\markdown\GithubMarkdown();
echo $parser->parse($markdown);
// use markdown extra
$parser = new \cebe\markdown\MarkdownExtra();
echo $parser->parse($markdown);
// parse only inline elements (useful for one-line descriptions)
$parser = new \cebe\markdown\GithubMarkdown();
echo $parser->parseParagraph($markdown); You may optionally set one of the following options on the parser object: For all Markdown Flavors:
For GithubMarkdown:
It is recommended to use UTF-8 encoding for the input strings. Other encodings may work, but are currently untested. The command line scriptYou can use it to render this readme:
Using github flavored markdown:
or convert the original markdown description to html using the unix pipe:
Here is the full Help output you will see when running
Security ConsiderationsBy design markdown allows HTML to be included within the markdown text. This also means that it may contain Javascript and CSS styles. This allows to be very flexible for creating output that is not limited by the markdown syntax, but it comes with a security risk if you are parsing user input as markdown (see XSS). In that case you should process the result of the markdown conversion with tools like HTML Purifier that filter out all elements which are not allowed for users to be added. The list of allowed elements for markdown could be configured as: [
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'hr',
'pre', 'code',
'blockquote',
'table', 'tr', 'td', 'th', 'thead', 'tbody',
'strong', 'em', 'b', 'i', 'u', 's', 'span',
'a', 'p', 'br', 'nobr',
'ul', 'ol', 'li',
'img',
], The list of allowed attributes would be: ['th.align', 'td.align', 'ol.start', 'code.class'] The above configuration is a general recommendation and may need to be adjusted dependent on your needs. ExtensionsHere are some extensions to this library:
Extending the languageMarkdown consists of two types of language elements, I'll call them block and inline elements simlar to what you have in
HTML with This markdown parser allows you to extend the markdown language by changing existing elements behavior and also adding new block and inline elements. You do this by extending from the parser class and adding/overriding class methods and properties. For the different element types there are different ways to extend them as you will see in the following sections. Adding block elementsThe markdown is parsed line by line to identify each non-empty line as one of the block element types.
To identify a line as the beginning of a block element it calls all protected class methods who's name begins with <?php
class MyMarkdown extends \cebe\markdown\Markdown
{
protected function identifyFencedCode($line, $lines, $current)
{
// if a line starts with at least 3 backticks it is identified as a fenced code block
if (strncmp($line, '```', 3) === 0) {
return true;
}
return false;
}
// ...
} In the above, Parsing of a block element is done in two steps:
Adding inline elementsAdding inline elements is different from block elements as they are parsed using markers in the text.
An inline element is identified by a marker that marks the beginning of an inline element (e.g. Parsing methods for inline elements are also protected and identified by the prefix As an example, we will add support for the strikethrough feature of github flavored markdown: <?php
class MyMarkdown extends \cebe\markdown\Markdown
{
/**
* @marker ~~
*/
protected function parseStrike($markdown)
{
// check whether the marker really represents a strikethrough (i.e. there is a closing ~~)
if (preg_match('/^~~(.+?)~~/', $markdown, $matches)) {
return [
// return the parsed tag as an element of the abstract syntax tree and call `parseInline()` to allow
// other inline markdown elements inside this tag
['strike', $this->parseInline($matches[1])],
// return the offset of the parsed text
strlen($matches[0])
];
}
// in case we did not find a closing ~~ we just return the marker and skip 2 characters
return [['text', '~~'], 2];
}
// rendering is the same as for block elements, we turn the abstract syntax array into a string.
protected function renderStrike($element)
{
return '<del>' . $this->renderAbsy($element[1]) . '</del>';
}
} Composing your own Markdown flavorThis markdown library is composed of traits so it is very easy to create your own markdown flavor by adding and/or removing the single feature traits. Designing your Markdown flavor consists of four steps:
Select a base classIf you want to extend from a flavor and only add features you can use one of the existing classes
( If you want to define a subset of the markdown language, i.e. remove some of the features, you have to
extend your class from Select language feature traitsThe following shows the trait selection for traditional Markdown. class MyMarkdown extends Parser
{
// include block element parsing using traits
use block\CodeTrait;
use block\HeadlineTrait;
use block\HtmlTrait {
parseInlineHtml as private;
}
use block\ListTrait {
// Check Ul List before headline
identifyUl as protected identifyBUl;
consumeUl as protected consumeBUl;
}
use block\QuoteTrait;
use block\RuleTrait {
// Check Hr before checking lists
identifyHr as protected identifyAHr;
consumeHr as protected consumeAHr;
}
// include inline element parsing using traits
use inline\CodeTrait;
use inline\EmphStrongTrait;
use inline\LinkTrait;
/**
* @var boolean whether to format markup according to HTML5 spec.
* Defaults to `false` which means that markup is formatted as HTML4.
*/
public $html5 = false;
protected function prepare()
{
// reset references
$this->references = [];
}
// ...
} In general, just adding the trait with There is also a conflict for parsing of the If you use any trait that uses the If you use the link trait it may be useful to implement Define escapeable charactersDepending on the language features you have chosen there is a different set of characters that can be escaped
using /**
* @var array these are "escapeable" characters. When using one of these prefixed with a
* backslash, the character will be outputted without the backslash and is not interpreted
* as markdown.
*/
protected $escapeCharacters = [
'\\', // backslash
'`', // backtick
'*', // asterisk
'_', // underscore
'{', '}', // curly braces
'[', ']', // square brackets
'(', ')', // parentheses
'#', // hash mark
'+', // plus sign
'-', // minus sign (hyphen)
'.', // dot
'!', // exclamation mark
'<', '>',
]; Add custom rendering behaviorOptionally you may also want to adjust rendering behavior by overriding some methods.
You may refer to the AcknowledgementsI'd like to thank @erusev for creating Parsedown which heavily influenced this work and provided the idea of the line based parsing approach. FAQWhy another markdown parser?While reviewing PHP markdown parsers for choosing one to use bundled with the Yii framework 2.0 I found that most of the implementations use regex to replace patterns instead of doing real parsing. This way extending them with new language elements is quite hard as you have to come up with a complex regex, that matches your addition but does not mess with other elements. Such additions are very common as you see on github which supports referencing issues, users and commits in the comments. A real parser should use context aware methods that walk trough the text and parse the tokens as they find them. The only implentation that I have found that uses this approach is Parsedown which also shows that this implementation is much faster than the regex way. Parsedown however is an implementation that focuses on speed and implements its own flavor (mainly github flavored markdown) in one class and at the time of this writing was not easily extensible. Given the situation above I decided to start my own implementation using the parsing approach from Parsedown and making it extensible creating a class for each markdown flavor that extend each other in the way that also the markdown languages extend each other. This allows you to choose between markdown language flavors and also provides a way to compose your own flavor picking the best things from all. I chose this approach as it is easier to implement and also more intuitive approach compared to using callbacks to inject functionallity into the parser. Where do I report bugs or rendering issues?Just open an issue on github, post your markdown code and describe the problem. You may also attach screenshots of the rendered HTML result to describe your problem. How can I contribute to this library?Check the CONTRIBUTING.md file for more info. Am I free to use this?This library is open source and licensed under the MIT License. This means that you can do whatever you want with it as long as you mention my name and include the license file. Check the license for details. ContactFeel free to contact me using email or twitter. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论