tags. * * @license CC0-1.0 * @author Nikola Smolenski */ class Poem { /** * Bind the renderPoem function to the tag * @param Parser $parser */ public static function init( Parser $parser ) { $parser->setHook( 'poem', [ self::class, 'renderPoem' ] ); } /** * Parse the text into proper poem format * @param string|null $in The text inside the poem tag * @param string[] $param * @param Parser $parser * @param PPFrame $frame * @return string */ public static function renderPoem( $in, array $param = [], Parser $parser, PPFrame $frame ) { // using newlines in the text will cause the parser to add

tags, // which may not be desired in some cases $newline = isset( $param['compact'] ) ? '' : "\n"; $tag = $parser->insertStripItem( "
" ); // replace colons with indented spans $text = preg_replace_callback( '/^(:+)(.+)$/m', [ self::class, 'indentVerse' ], $in ); // replace newlines with
tags unless they are at the beginning or end // of the poem $text = preg_replace( [ "/^\n/", "/\n$/D", "/\n/" ], [ "", "", "$tag\n" ], $text ); // replace spaces at the beginning of a line with non-breaking spaces $text = preg_replace_callback( '/^( +)/m', [ self::class, 'replaceSpaces' ], $text ); $text = $parser->recursiveTagParse( $text, $frame ); $attribs = Sanitizer::validateTagAttributes( $param, 'div' ); // Wrap output in a

with "poem" class. if ( isset( $attribs['class'] ) ) { $attribs['class'] = 'poem ' . $attribs['class']; } else { $attribs['class'] = 'poem'; } return Html::rawElement( 'div', $attribs, $newline . trim( $text ) . $newline ); } /** * Callback for preg_replace_callback() that replaces spaces with non-breaking spaces * @param string[] $m Matches from the regular expression * - $m[1] consists of 1 or more spaces * @return string */ protected static function replaceSpaces( array $m ) { return str_replace( ' ', ' ', $m[1] ); } /** * Callback for preg_replace_callback() that wraps content in an indented span * @param string[] $m Matches from the regular expression * - $m[1] consists of 1 or more colons * - $m[2] consists of the text after the colons * @return string */ protected static function indentVerse( array $m ) { $attribs = [ 'class' => 'mw-poem-indented', 'style' => 'display: inline-block; margin-left: ' . strlen( $m[1] ) . 'em;' ]; // @todo Should this really be raw? return Html::rawElement( 'span', $attribs, $m[2] ); } }