\s|^```|\*\*[^*\n]+\*\*|\[[^\]\n]+\]\([^)\s]+\)/m', $text ); } public static function to_html( $text ) { $text = str_replace( array( "\r\n", "\r" ), "\n", (string) $text ); $lines = explode( "\n", $text ); $html = array(); $para = array(); $count = count( $lines ); $flush = function () use ( &$para, &$html ) { if ( $para ) { $html[] = '
' . implode( "
\n", array_map( array( __CLASS__, 'inline' ), $para ) ) . '
' . esc_html( implode( "\n", $code ) ) . '';
continue;
}
if ( '' === trim( $line ) ) {
$flush();
continue;
}
if ( preg_match( '/^\s{0,3}(#{1,6})\s+(.+?)\s*#*\s*$/', $line, $m ) ) {
$flush();
$level = strlen( $m[1] );
$html[] = "' . self::to_html( implode( "\n", $quote ) ) . ''; continue; } if ( self::list_item( $line ) ) { $flush(); $html[] = self::render_list( $lines, $i ); continue; } $para[] = $line; } $flush(); return implode( "\n", $html ); } /** @return array|null array( indent, ordered, text ) */ protected static function list_item( $line ) { if ( preg_match( '/^(\s*)([-*+]|\d+[.)])\s+(.*)$/', $line, $m ) ) { return array( strlen( str_replace( "\t", ' ', $m[1] ) ), ctype_digit( rtrim( $m[2], '.)' ) ), $m[3] ); } return null; } /** Consume list lines from $i (left on the last list line). */ protected static function render_list( $lines, &$i ) { $first = self::list_item( $lines[ $i ] ); $base = $first[0]; $tag = $first[1] ? 'ol' : 'ul'; $items = array(); $count = count( $lines ); for ( ; $i < $count; $i++ ) { $item = self::list_item( $lines[ $i ] ); if ( ! $item ) { // A non-blank, indented continuation line belongs to the last item. if ( $items && '' !== trim( $lines[ $i ] ) && preg_match( '/^\s+/', $lines[ $i ] ) ) { $items[ count( $items ) - 1 ]['text'] .= ' ' . trim( $lines[ $i ] ); continue; } break; } if ( $item[0] > $base && $items ) { $items[ count( $items ) - 1 ]['sub'] = self::render_list( $lines, $i ); continue; } if ( $item[0] < $base ) { break; } $items[] = array( 'text' => $item[2], 'sub' => '', ); } --$i; $out = "<{$tag}>"; foreach ( $items as $item ) { $out .= '
' . esc_html( $m[1] ) . '';
return "\x1A" . ( count( $codes ) - 1 ) . "\x1A";
},
$text
);
$text = preg_replace_callback(
'/!\[([^\]]*)\]\(\s*([^)\s]+)(?:\s+"([^"]*)")?\s*\)/',
function ( $m ) {
return '