-
Notifications
You must be signed in to change notification settings - Fork 0
/
MarkdownToHabrahabrConverter.php
108 lines (90 loc) · 3.11 KB
/
MarkdownToHabrahabrConverter.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<?php
/**
* Allows to convert an article in markdown syntax right to correct
* habrahabr article that is ready to publish.
*/
class MarkdownToHabrahabrConverter
{
public function convert($txt)
{
$txt = $this->convertSources($txt);
$txt = $this->convertImages($txt);
$txt = $this->convertLinks($txt);
$txt = $this->convertHeaders($txt);
$txt = $this->convertInlines($txt);
$txt = $this->convertLists($txt);
$txt = $this->convertBlockquotes($txt);
return $txt;
}
/* TODO: refactor */
protected function convertSources($txt)
{
$txt = preg_replace('/[\n\r]*```([\w]*)(.+?)```[\n\r]*/s', "\n\n<source lang=\"$1\">$2</source>\n", $txt);
return $txt;
}
protected function convertImages($txt)
{
$txt = preg_replace('/\!\[([^\n\r]+?)\][ \t]*\((.+?)\)/s', '<img src="$2" alt="$1"></img>', $txt);
return $txt;
}
protected function convertLinks($txt)
{
$txt = preg_replace('/\[([^\n\r]+?)\][ \t]*\((http.+?)\)/s', '<a href="$2">$1</a>', $txt);
return $txt;
}
protected function convertHeaders($txt)
{
$txt = $this->parseStringLiteral($txt, '####', 'h6');
$txt = $this->parseStringLiteral($txt, '###', 'h5');
$txt = $this->parseStringLiteral($txt, '##', 'h4');
return $txt;
}
protected function convertInlines($txt)
{
$txt = $this->parseInlineLiteral($txt, '**', 'b');
$txt = $this->parseInlineLiteral($txt, '_', 'i');
$txt = $this->parseInlineLiteral($txt, '`', 'code');
return $txt;
}
protected function convertLists($txt)
{
$txt = preg_replace('/((^( *\* +([^\n\r]+)[^\n]+)$[\n]+)+)/m', "<ul>\n$1</ul>\n", $txt);
$txt = preg_replace('/^( *\* +([^\n\r]+)[^\n]+)$/m', "<li>$2</li>", $txt);
return $txt;
}
protected function convertBlockquotes($txt)
{
$txt = preg_replace('/((^( *\> +([^\n\r]+)[^\n]+)$\s+)+)/m', "<blockquote>\n$1</blockquote>\n", $txt);
$txt = preg_replace('/^ *\> +(([^\n\r]+)[^\n]+$)/m', "$1", $txt);
return $txt;
}
protected function parseInlineLiteral($string, $delimiter, $tag)
{
$u = $this->addSlashes($this->extractUniqueSymbols($delimiter));
$d = $this->addSlashes($delimiter);
return preg_replace(
'/(\s+|^)' . $d . '([^' . $u . '\n\r]+?[^' . $u . ' \t]+)' . $d . '/m',
'$1<' . $tag . '>$2</' . $tag . '>',
$string
);
}
protected function parseStringLiteral($string, $prefix, $tag)
{
$p = $this->addSlashes($prefix);
return preg_replace(
'/^\s*' . $p . '[ \t]+(.+?)\s*$/ms',
'<' . $tag . '>$1</' . $tag . '>',
$string
);
}
private function extractUniqueSymbols($string)
{
$allSymbolsArray = str_split($string);
$uniqueSymbolsArray = array_unique($allSymbolsArray);
return implode('', $uniqueSymbolsArray);
}
private function addSlashes($string)
{
return preg_replace('/(.)/s', '\\\$1', $string); // abc => /a/b/c
}
}