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