' . self::html( $m[1] ) . ''; } elseif ( preg_match( '/^`([^`]+)`$/u', $part, $m ) ) { $out .= '' . esc_html( $m[1] ) . ''; } elseif ( preg_match( '/^\[([^\]]+)\]\(([^)\s]+)\)$/u', $part, $m ) ) { $href = esc_url( $m[2] ); $out .= '' !== $href ? '' . self::html( $m[1] ) . '' : self::html( $m[1] ); } else { $out .= esc_html( $part ); } } return $out; } public static function blocks( $text, array $p_attrs = array(), array $first = array() ) { $lines = array(); foreach ( is_array( $text ) ? $text : array( (string) $text ) as $chunk ) { foreach ( preg_split( '/\r\n|\r|\n/', (string) $chunk ) ?: array() as $line ) { $lines[] = $line; } $lines[] = ''; } $out = ''; $para = array(); $list = array(); $kind = ''; $flush = static function () use ( &$para, &$list, &$kind, &$out, $p_attrs, &$first ) { if ( $para ) { $prefix = (string) ( $first['prefix'] ?? '' ); $out .= AIEO_Content_Blocks::paragraph( (array) ( $first['attrs'] ?? array() ) + $p_attrs, $prefix . implode( '
', array_map( array( __CLASS__, 'html' ), $para ) ) ); $para = array(); $first = array(); } if ( $list ) { $out .= AIEO_Content_Blocks::list_block( array(), array_map( array( __CLASS__, 'html' ), $list ), 'ol' === $kind ); $list = array(); $kind = ''; } }; foreach ( $lines as $line ) { $line = trim( $line ); if ( '' === $line ) { $flush(); } elseif ( preg_match( '/^(#{2,4})\s+(.+)$/u', $line, $m ) ) { $flush(); $out .= AIEO_Content_Blocks::heading( array( 'level' => strlen( $m[1] ) ), self::html( $m[2] ) ); } elseif ( preg_match( '/^[-*]\s+(.+)$/u', $line, $m ) ) { if ( $para || 'ol' === $kind ) { $flush(); } $kind = 'ul'; $list[] = $m[1]; } elseif ( preg_match( '/^\d+[.)]\s+(.+)$/u', $line, $m ) ) { if ( $para || 'ul' === $kind ) { $flush(); } $kind = 'ol'; $list[] = $m[1]; } else { if ( $list ) { $flush(); } $para[] = $line; } } $flush(); return $out; } public static function plain( $text ) { $text = preg_replace( '/\*\*(.+?)\*\*/su', '$1', (string) $text ); $text = preg_replace( '/`([^`]+)`/u', '$1', $text ); return (string) preg_replace( '/\[([^\]]+)\]\([^)\s]+\)/u', '$1', $text ); } const COLOURS = array( 'accent' => 'accent-text', 'success' => 'success', 'warning' => 'warning-ink', 'danger' => 'danger' ); const COLOUR_TOKEN = '/\{\{([a-z][a-z0-9-]*):([^{}]+)\}\}/u'; const LINE_BREAK = ' // '; public static function heading( $text ) { $out = ''; foreach ( preg_split( '/(\{\{[a-z][a-z0-9-]*:[^{}]+\}\})/u', (string) $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ) ?: array() as $part ) { if ( preg_match( '/^' . substr( self::COLOUR_TOKEN, 1, -2 ) . '$/u', $part, $m ) && isset( self::COLOURS[ $m[1] ] ) ) { $out .= '' . self::html( $m[2] ) . ''; } else { $out .= self::html( $part ); } } return str_replace( self::LINE_BREAK, '
', $out ); } public static function heading_plain( $text ) { $text = (string) preg_replace_callback( self::COLOUR_TOKEN, static fn ( $m ) => isset( self::COLOURS[ $m[1] ] ) ? $m[2] : $m[0], (string) $text ); return str_replace( self::LINE_BREAK, ' ', self::plain( $text ) ); } public static function heading_text( $html ) { $html = (string) preg_replace_callback( '#]*\bclass="has-inline-color has-([a-z0-9-]+)-color"[^>]*>(.*?)#su', static function ( $m ) { $tone = array_search( $m[1], self::COLOURS, true ); return false === $tone ? $m[2] : '{{' . $tone . ':' . $m[2] . '}}'; }, (string) $html ); return self::text( (string) preg_replace( '# ?#i', self::LINE_BREAK, $html ) ); } public static function text( $html ) { $html = (string) $html; $html = preg_replace( '#<(strong|b)\b[^>]*>(.*?)#su', '**$2**', $html ); $html = preg_replace( '#]*>(.*?)#su', '`$1`', $html ); $html = preg_replace_callback( '#]*href="([^"]*)"[^>]*>(.*?)#su', static function ( $m ) { return '[' . $m[2] . '](' . html_entity_decode( $m[1], ENT_QUOTES | ENT_HTML5, 'UTF-8' ) . ')'; }, $html ); $html = preg_replace( '##i', "\n", $html ); return trim( html_entity_decode( wp_strip_all_tags( $html ), ENT_QUOTES | ENT_HTML5, 'UTF-8' ) ); } }