* Website: https://github.com/jbroadway/slimdown
* License: MIT
*/
class Slimdown {
public static $rules = array (
'/```(.*?)```/s' => self::class .'::code_parse', // code blocks
'/\n(#+)\s+(.*)/' => self::class .'::header', // headers
'/\!\[([^\[]*?)\]\(([^\)]+)\)/' => self::class .'::img', // images
'/\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::link', // links
'/(\*\*|__)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '\2', // bold
'/(\*|_)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '\2', // emphasis
'/(\~\~)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '\2', // del
'/\:\"(.*?)\"\:/' => '\1
', // quote
'/`(.*?)`/' => '\1', // inline code
'/\n\*(.*)/' => self::class .'::ul_list', // ul lists
'/\n[0-9]+\.(.*)/' => self::class .'::ol_list', // ol lists
'/\n(>|\>)(.*)/' => self::class .'::blockquote', // blockquotes
'/\n-{5,}/' => "\n
/' => "\n", // fix extra blockquote '//' => self::class .'::fix_link', // fix links '/self::class .'::fix_img', // fix images '/
{{{([0-9]+)}}}<\/p>/s' => self::class .'::reinsert_code_blocks' // re-insert code blocks ); private static $code_blocks = []; private static function code_parse ($regs) { $item = $regs[1]; $item = htmlentities ($item, ENT_COMPAT); $item = str_replace ("\n\n", '
', $item); $item = str_replace ("\n", '
', $item); while (mb_substr ($item, 0, 4) === '
') { $item = mb_substr ($item, 4); } while (mb_substr ($item, -4) === '
') { $item = mb_substr ($item, 0, -4); } // Store code blocks with placeholders to avoid other regexes affecting them self::$code_blocks[] = sprintf ("", trim ($item)); return sprintf ("{{{%d}}}", count (self::$code_blocks) - 1); } private static function reinsert_code_blocks ($regs) { // Reinsert the stored code blocks at the end $index = $regs[1]; return self::$code_blocks[$index]; } private static function para ($regs) { $line = $regs[1]; $trimmed = trim ($line); if (preg_match ('/^<\/?(ul|ol|li|h|p|bl|table|tr|th|td|code)/', $trimmed)) { return "\n" . $line . "\n"; } if (! empty ($trimmed)) { //return sprintf ("\n%s%s
\n", $trimmed); return sprintf ("\n%s\n", $trimmed); } return $trimmed; } private static function ul_list ($regs) { $item = $regs[1]; return sprintf ("\n\n\t
", trim ($item)); } private static function ol_list ($regs) { $item = $regs[1]; return sprintf ("\n- %s
\n\n\t
", trim ($item)); } private static function blockquote ($regs) { $item = $regs[2]; return sprintf ("\n- %s
\n%s", trim ($item)); } private static function header ($regs) { list ($tmp, $chars, $header) = $regs; $level = strlen ($chars); return sprintf ('%s ', $level, trim ($header), $level); } private static function link ($regs) { list ($tmp, $text, $link) = $regs; // Substitute _ and * in links so they don't break the URLs $link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link); return sprintf ('%s', $link, $text); } private static function img ($regs) { list ($tmp, $text, $link) = $regs; // Substitute _ and * in links so they don't break the URLs $link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link); return sprintf ('', $link, $text); //return sprintf ('
', $link, $text); // added support for thumbnail generation on the fly } private static function fix_link ($regs) { // Replace substitutions so links are preserved $fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]); return sprintf ('', $fixed_link); } private static function fix_img ($regs) { // Replace substitutions so links are preserved $fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]); return sprintf ('
$replacement) { if (is_callable ( $replacement)) { $text = preg_replace_callback ($regex, $replacement, $text); } else { $text = preg_replace ($regex, $replacement, $text); } } return trim ($text); } }