File: Poem.php

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (95 lines) | stat: -rw-r--r-- 2,708 bytes parent folder | download | duplicates (2)
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( '&#160;', 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 );
	}
}