Custom PointParser for Markdown implemented.
This commit is contained in:
parent
76fc484361
commit
42d504aba5
|
@ -79,3 +79,7 @@ swiftmailer:
|
||||||
username: "%mailer_user%"
|
username: "%mailer_user%"
|
||||||
password: "%mailer_password%"
|
password: "%mailer_password%"
|
||||||
spool: { type: memory }
|
spool: { type: memory }
|
||||||
|
|
||||||
|
knp_markdown:
|
||||||
|
parser:
|
||||||
|
service: markdown.parser.point
|
|
@ -51,3 +51,10 @@ services:
|
||||||
- @skobkin__point_tools.service_factory.comment_factory
|
- @skobkin__point_tools.service_factory.comment_factory
|
||||||
- @skobkin__point_tools.service_factory.tag_factory
|
- @skobkin__point_tools.service_factory.tag_factory
|
||||||
|
|
||||||
|
markdown.parser.point:
|
||||||
|
class: Skobkin\Bundle\PointToolsBundle\Service\Markdown\PointParser
|
||||||
|
arguments:
|
||||||
|
- []
|
||||||
|
- @router
|
||||||
|
tags:
|
||||||
|
- { name: markdown.parser }
|
|
@ -0,0 +1,206 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Skobkin\Bundle\PointToolsBundle\Service\Markdown;
|
||||||
|
|
||||||
|
use Knp\Bundle\MarkdownBundle\Parser\MarkdownParser;
|
||||||
|
use Symfony\Component\Routing\RouterInterface;
|
||||||
|
|
||||||
|
class PointParser extends MarkdownParser
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var RouterInterface
|
||||||
|
*/
|
||||||
|
protected $router;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected $features = array(
|
||||||
|
'header' => true,
|
||||||
|
'list' => true,
|
||||||
|
'horizontal_rule' => true,
|
||||||
|
'table' => false,
|
||||||
|
'foot_note' => true,
|
||||||
|
'fenced_code_block' => true,
|
||||||
|
'abbreviation' => true,
|
||||||
|
'definition_list' => true,
|
||||||
|
'inline_link' => true, // [link text](url "optional title")
|
||||||
|
'reference_link' => true, // [link text] [id]
|
||||||
|
'shortcut_link' => true, // [link text]
|
||||||
|
'images' => true,
|
||||||
|
'block_quote' => true,
|
||||||
|
'code_block' => true,
|
||||||
|
'html_block' => false,
|
||||||
|
'auto_link' => true,
|
||||||
|
'auto_mailto' => true,
|
||||||
|
'entities' => true,
|
||||||
|
'no_html' => true,
|
||||||
|
'point_usernames' => true, // @user
|
||||||
|
'point_posts' => true, // #post
|
||||||
|
'point_tags' => false, // @todo implement
|
||||||
|
'point_inline_images' => true, // https://i.skobk.in/i/facepalm.jpg
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct(array $features, RouterInterface $router)
|
||||||
|
{
|
||||||
|
$this->router = $router;
|
||||||
|
|
||||||
|
parent::__construct($features);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Point.im breaks Markdown rule about quotation on next line
|
||||||
|
*
|
||||||
|
* @param $text
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function doBlockQuotes($text) {
|
||||||
|
$text = preg_replace_callback('/
|
||||||
|
( # Wrap whole match in $1
|
||||||
|
(?>
|
||||||
|
^[ ]*>[ ]? # ">" at the start of a line
|
||||||
|
.+\n # rest of the first line
|
||||||
|
\n* # blanks
|
||||||
|
)+
|
||||||
|
)
|
||||||
|
/xm',
|
||||||
|
array($this, '_doBlockQuotes_callback'), $text
|
||||||
|
);
|
||||||
|
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Point.im breaks Markdown double line wrap rule
|
||||||
|
*
|
||||||
|
* @param $text
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function formParagraphs($text) {
|
||||||
|
#
|
||||||
|
# Params:
|
||||||
|
# $text - string to process with html <p> tags
|
||||||
|
#
|
||||||
|
# Strip leading and trailing lines:
|
||||||
|
$text = preg_replace('/\A\n+|\n+\z/', '', $text);
|
||||||
|
|
||||||
|
$grafs = preg_split('/\n+/', $text, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Wrap <p> tags and unhashify HTML blocks
|
||||||
|
#
|
||||||
|
foreach ($grafs as $key => $value) {
|
||||||
|
if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
|
||||||
|
# Is a paragraph.
|
||||||
|
$value = $this->runSpanGamut($value);
|
||||||
|
$value = preg_replace('/^([ ]*)/', "<p>", $value);
|
||||||
|
$value .= "</p>";
|
||||||
|
$grafs[$key] = $this->unhash($value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Is a block.
|
||||||
|
# Modify elements of @grafs in-place...
|
||||||
|
$graf = $value;
|
||||||
|
$block = $this->html_hashes[$graf];
|
||||||
|
$graf = $block;
|
||||||
|
$grafs[$key] = $graf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n\n", $grafs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $text
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function doAutoLinks($text)
|
||||||
|
{
|
||||||
|
if ($this->features['point_inline_images']) {
|
||||||
|
return preg_replace_callback('{((https?):\/\/[^\'">\s]+\.(jpg|jpeg|png|gif))}i', array(&$this, 'doAutoLinksInlineImageCallback'), $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::doAutoLinks($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function doAnchors($text)
|
||||||
|
{
|
||||||
|
$text = parent::doAnchors($text);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Turn Markdown link shortcuts into XHTML <a> tags.
|
||||||
|
#
|
||||||
|
if ($this->in_anchor) {
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
$this->in_anchor = true;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Handling username links: @some-point-username
|
||||||
|
#
|
||||||
|
if ($this->features['point_usernames']) {
|
||||||
|
$text = preg_replace_callback('{
|
||||||
|
( # wrap whole match in $1
|
||||||
|
@
|
||||||
|
(
|
||||||
|
[a-zA-Z0-9\-]+? # username = $2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
([^a-zA-Z0-9\-]|$) # Tail of username
|
||||||
|
}xs',
|
||||||
|
array(&$this, 'doAnchorsPointUsernameCallback'), $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Handling post links: #somepost
|
||||||
|
#
|
||||||
|
if ($this->features['point_posts']) {
|
||||||
|
$text = preg_replace_callback('{
|
||||||
|
( # wrap whole match in $1
|
||||||
|
\#
|
||||||
|
(
|
||||||
|
[a-zA-Z]+? # post id = $2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
([^a-zA-Z]|$) # Tail of post
|
||||||
|
}xs',
|
||||||
|
array(&$this, 'doAnchorsPointPostCallback'), $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->in_anchor = false;
|
||||||
|
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function doAutoLinksInlineImageCallback($matches)
|
||||||
|
{
|
||||||
|
$url = trim($matches[1]);
|
||||||
|
$ext = $matches[2];
|
||||||
|
|
||||||
|
return $this->hashPart('<a href="'.$url.'" class="post-image '
|
||||||
|
.('gif' === $ext ? ' img-gif':'').'"><img src="'.$url.'" class="img-thumbnail" alt="Inline image"></a>');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function doAnchorsPointUsernameCallback($matches)
|
||||||
|
{
|
||||||
|
//$wholeMatch = $matches[1];
|
||||||
|
$username = $matches[2];
|
||||||
|
$href = $this->router->generate('user_show', ['login' => $username]);
|
||||||
|
$tail = htmlspecialchars($matches[3]);
|
||||||
|
|
||||||
|
return $this->hashPart('<a href="'.$href.'" class="user">@'.$username.'</a>'.$tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function doAnchorsPointPostCallback($matches)
|
||||||
|
{
|
||||||
|
//$wholeMatch = $matches[1];
|
||||||
|
$postId = $matches[2];
|
||||||
|
$href = $this->router->generate('post_show', ['id' => $postId]);
|
||||||
|
$tail = htmlspecialchars($matches[3]);
|
||||||
|
|
||||||
|
return $this->hashPart('<a href="'.$href.'" class="post">#'.$postId.'</a>'.$tail);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue