Полный декодер кода Морзе. Надеюсь, это поможет и кому-то другому.
public function format(string $text)
{
$rules = array(
'/^(?!(\*\s)|(#)).*/' => 'p',
'/^\*\s(.*)/' => 'li',
"/(^#{1,6})(.*)/" => "h"
);
foreach ($rules as $rule => $replacement) {
$matched = preg_match ($rule, $text);
if (!empty($matched)) {
return $parsed = preg_replace_callback ($rule, function ($output) use ($replacement, $rule) {
if ($replacement === "h") {
$strongHeading = preg_match ('/^(\*{2})([\w].*?)(\*{2})$/', trim ($output[2]), $strongHeaderOutPut);
if ($strongHeading === 0) {
//multiple or single nested strong
$strongFound = preg_match_all ('/(\*{2})(\w.*?)(\*{2})/', trim ($output[2]), $out);
if ($strongFound !== 0) {
$multipleStrongWords = preg_replace ('/(\*{2})(\w.*?)(\*{2})/', '< strong>${2}< /strong>', $output[2]);
return "< h1>" . trim ($multipleStrongWords) . "< /h1>";
} else {
if ($output[1] === "#") {
return "< h1>" . trim ($output[2]) . "< /h1>";
} elseif ($output[1] === "##") {
return "< h2>" . trim ($output[2]) . "< /h2>";
} elseif ($output[1] === "###") {
return "< h3>" . trim ($output[2]) . "< /h3>";
} elseif ($output[1] === "####") {
return "< h4>" . trim ($output[2]) . "< /h4>";
} elseif ($output[1] === "#####") {
return "< h5>" . trim ($output[2]) . "< /h5>";
} elseif ($output[1] === "######") {
return "< h6>" . trim ($output[2]) . "< /h6>";
}
}
} elseif ($strongHeading === 1) {
return "< h1>< strong>" . trim ($strongHeaderOutPut[2]) . "< /strong>< /h1>";
}
} elseif ($replacement === "p") {
//multiple or single nested strong
$strongFound = preg_match_all ('/(\*{2})(\w.*?)(\*{2})/', $output[0], $out);
if ($strongFound !== 0) {
$multipleStrongWords = preg_replace ('/(\*{2})(\w.*?)(\*{2})/', '< strong>${2}< /strong>', $output[0]);
return "< p>" . trim ($multipleStrongWords) . "< /p>";
}
$compoundAsterisks = preg_match_all ("/(\*{2})(\*.*?)(\*{2})/", $output[0], $out);
if ($compoundAsterisks !== 0) {
$multipleStrongWords = preg_replace ('/(\*{2})(\*.*?)(\*{2})/', '< strong>${2}< /strong>', $output[0]);
return "< p>" . trim ($multipleStrongWords) . "< /p>";
}
return "< p>" . trim ($output[0]) . "< /p>";
} elseif ($replacement === "li") {
//multiple or single nested strong
$strongFound = preg_match_all ('/(\*{2})(\w.*?)(\*{2})/', $output[1], $out);
if ($strongFound !== 0) {
$multipleStrongWords = preg_replace ('/(\*{2})(\w.*?)(\*{2})/', '< strong>${2}< /strong>', $output[1]);
return "< li>" . ( $multipleStrongWords ) . "< /li>";
}
$compoundAsterisks = preg_match_all ("/(\*{2})(.*?\s)(\*{2})/", $output[1], $out);
if ($compoundAsterisks !== 0) {
$multipleStrongWords = preg_replace ('/(\*{2})(.*?\s)(\*{2})/', '< strong>${2}< /strong>', $output[1]);
return "< li>" . trim ($multipleStrongWords) . "< /li>";
}
return "< li>" . trim ($output[1]) . "< /li>";
}
}, $text);
}
}
}
Тесты приведены ниже.
public function test_markdown_format_to_html()
{
$this->assertEquals ($this->mardown->format ('# dolor sit amet, consectetur adipiscing elit. Integer a neque eros. Integer pellentesque leo'), '< h1>dolor sit amet, consectetur adipiscing elit. Integer a neque eros. Integer pellentesque leo< /h1>', 'Should work for level-1 header');
$this->assertEquals($this->mardown->format ('## consectetur adipiscing elit. Integer a neque eros. Integer pellentesque leo'), '< h2>consectetur adipiscing elit. Integer a neque eros. Integer pellentesque leo< /h2>', 'Should work for level-2 header');
$this->assertEquals ($this->mardown->format ('### sed, viverra'), '< h3>sed, viverra< /h3>', 'Should work for level-3 header');
$this->assertEquals ($this->mardown->format ('#### Class aptent'), '< h4>Class aptent< /h4>', 'Should work for level-4 header');
$this->assertEquals ($this->mardown->format ('##### rutrum mi eu, finibus interdum tortor. Class aptent taciti sociosqu ad'), '< h5>rutrum mi eu, finibus interdum tortor. Class aptent taciti sociosqu ad< /h5>', 'Should work for level-5 header');
$this->assertEquals ($this->mardown->format ('###### pellentesque leo ac blandit luctus. Sed a eros eget arcu laoreet'), '< h6>pellentesque leo ac blandit luctus. Sed a eros eget arcu laoreet< /h6>', 'Should work for level-6 header');
$this->assertEquals ($this->mardown->format ('####### Maecenas erat dolor, euismod rutrum mi eu, finibus interdum tortor.'), '< h6># Maecenas erat dolor, euismod rutrum mi eu, finibus interdum tortor.< /h6>', 'Should for strings starting with more than 6 hashtags');
$this->assertEquals ($this->mardown->format ('* eget'), '< li>eget< /li>', 'Should work for list items');
$this->assertEquals ($this->mardown->format ('# **ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas rutrum nisl eu**'), '< h1>< strong>ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas rutrum nisl eu< /strong>< /h1>', 'Should work for strings with emphasis');
$this->assertEquals ($this->mardown->format ('blandit luctus. Sed a eros eget arcu laoreet suscipit. Maecenas ac urna tincidunt, fermentum'), '< p>blandit luctus. Sed a eros eget arcu laoreet suscipit. Maecenas ac urna tincidunt, fermentum< /p>', 'Should work for text without markup');
$this->assertEquals($this->mardown->format ('**ad litora torquent per conubia nostra, per inceptos himenaeos.**'), '< p>< strong>ad litora torquent per conubia nostra, per inceptos himenaeos.< /strong>< /p>', 'Should work for strings with emphasis');
$this->assertEquals ($this->mardown->format ('suscipit. Maecenas ac urna tincidunt, **fermentum** massa sed, viverra elit. Maecenas'), '< p>suscipit. Maecenas ac urna tincidunt, < strong>fermentum< /strong> massa sed, viverra elit. Maecenas< /p>', 'Should work for strings with partial emphasis');
$this->assertEquals ($this->mardown->format ('# rutrum mi eu, **finibus interdum** tortor. Class aptent'), '< h1>rutrum mi eu, < strong>finibus interdum< /strong> tortor. Class aptent< /h1>', 'Should work for strings with partial emphasis');
$this->assertEquals($this->mardown->format ('* elit. Maecenas **e**rat dolor,'), '< li>elit. Maecenas < strong>e< /strong>rat dolor,< /li>', 'Should work for strings with partial emphasis');
$this->assertEquals ($this->mardown->format ('eros eget arcu **laoreet** suscipit. Maecenas ac urna tincidunt, **fermentum** massa sed, viverra'), '< p>eros eget arcu < strong>laoreet< /strong> suscipit. Maecenas ac urna tincidunt, < strong>fermentum< /strong> massa sed, viverra< /p>', 'Should work for strings where 2 parts of the string are emphasized');
$this->assertEquals ($this->mardown->format ('# pellentesque leo ac **blandit luctus**. Sed a eros eget **arcu laoreet suscipit. Maecenas ac**'), '< h1>pellentesque leo ac < strong>blandit luctus< /strong>. Sed a eros eget < strong>arcu laoreet suscipit. Maecenas ac< /strong>< /h1>', 'Should work for strings where 2 parts of the string are emphasized');
$this->assertEquals ($this->mardown->format ('* **himenaeos. Maecenas** rutrum **nisl eu** bibendum sodales'), '< li>< strong>himenaeos. Maecenas< /strong> rutrum < strong>nisl eu< /strong> bibendum sodales< /li>', 'Should work for strings where 2 parts of the string are emphasized');
$this->assertEquals ($this->mardown->format ('rutrum mi e*u, finibus **inter**dum**'), '< p>rutrum mi e*u, finibus < strong>inter< /strong>dum**< /p>', 'Should work when string contains random asterisks');
$this->assertEquals ($this->mardown->format ('****'), '< p>****< /p>', 'Compound asterisks 1');
$this->assertEquals ($this->mardown->format ('*****'), '< p>< strong>*< /strong>< /p>', 'Compound asterisks 2');
$this->assertEquals ($this->mardown->format ('***** **** *** ** *'), '< p>< strong>*< /strong> < strong>** < /strong>* ** *< /p>', 'Compound asterisks 4');
$this->assertEquals ($this->mardown->format ('* ** *** **** *****'), '< li>< strong> < /strong>* < strong>** < /strong>***< /li>', 'Compound asterisks 3');
}