1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
<?php
namespace MediaWiki\Extension\Poem;
use MediaWiki\Hook\ParserFirstCallInitHook;
use MediaWiki\Html\Html;
use MediaWiki\Parser\Parser;
use MediaWiki\Parser\PPFrame;
use MediaWiki\Parser\Sanitizer;
/**
* This class handles formatting poems in WikiText, specifically anything within
* <poem></poem> tags.
*
* @license CC0-1.0
* @author Nikola Smolenski <smolensk@eunet.yu>
*/
class Poem implements ParserFirstCallInitHook {
/**
* Bind the renderPoem function to the <poem> tag
* @param Parser $parser
*/
public function onParserFirstCallInit( $parser ) {
$parser->setHook( 'poem', [ $this, '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 function renderPoem( $in, array $param, Parser $parser, PPFrame $frame ) {
// using newlines in the text will cause the parser to add <p> tags,
// which may not be desired in some cases
$newline = isset( $param['compact'] ) ? '' : "\n";
$tag = $parser->insertStripItem( "<br />" );
// replace colons with indented spans
$text = preg_replace_callback(
'/^(:++)(.+)$/m',
static function ( array $matches ) {
$indentation = strlen( $matches[1] ) . 'em';
return Html::rawElement(
'span',
[
'class' => 'mw-poem-indented',
'style' => 'display: inline-block; ' .
"margin-inline-start: $indentation;",
],
$matches[2]
);
},
$in ?? ''
);
// replace newlines with <br /> tags unless they are at the beginning or end
// of the poem, or would directly follow exactly 4 dashes. See Parser::internalParse() for
// the exact syntax for horizontal rules.
$text = preg_replace(
[ '/^\n/', '/\n$/D', '/(?<!^----)\n/m' ],
[ "", "", "$tag\n" ],
$text
);
// replace spaces at the beginning of a line with non-breaking spaces
$text = preg_replace_callback(
'/^ +/m',
static function ( array $matches ) {
return str_repeat( ' ', strlen( $matches[0] ) );
},
$text
);
$text = $parser->recursiveTagParse( $text, $frame );
// Because of limitations of the regular expression above, horizontal rules with more than 4
// dashes still need special handling.
$text = str_replace( '<hr />' . $tag, '<hr />', $text );
$attribs = Sanitizer::validateTagAttributes( $param, 'div' );
// Wrap output in a <div> 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 );
}
}
|