1<?php
2/**
3 * <spoiler> tag for dokuwiki. Allows sections that are initially hidden, and
4 * are shown when a "Show" button is clicked. The spoiler can be hidden again
5 * by pressing the button.
6 *
7 * <spoiler>Content with default title</spoiler>
8 * <spoiler |Plot details>The butler did it!</spoiler>
9 *
10 * @license    GPL 3 (https://www.gnu.org/licenses/gpl-3.0.html)
11 * @author     halbbit (osi@abwesend.de)
12               heavily based on the abandoned version of Heikki Hokkanen <hoxu@users.sf.net>
13 */
14
15if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
16if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
17require_once(DOKU_PLUGIN.'syntax.php');
18
19class syntax_plugin_spoiler extends DokuWiki_Syntax_Plugin {
20
21	function getInfo(){
22		return array(
23			'author' => 'halbbit',
24			'email'  => 'supp3@gmx.net',
25			'date'   => '2021-03-03',
26			'name'   => 'spoiler2 plugin',
27			'desc'   => 'Add <spoiler> tag, allowing sections that are initially hidden and can be made visible by clicking on a button. Another click will hide the spoiler again',
28			'url'    => 'http://wiki.splitbrain.org/plugin:spoiler2',
29		);
30	}
31
32	function getType(){
33		return 'container';
34	}
35
36	function getPType() {
37		return 'block';
38	}
39
40	function getAllowedTypes() {
41		return array('container', 'substition', 'protected', 'disabled', 'formatting', 'paragraphs');
42	}
43
44	function getSort(){
45		return 195;
46	}
47
48    // override default accepts() method to allow nesting
49    // - ie, to get the plugin accepts its own entry syntax
50	function accepts($mode) {
51		// ($mode == 'plugin_spoiler')
52		if ($mode == substr(get_class($this), 7)) return true;
53
54		return parent::accepts($mode);
55	}
56
57	function connectTo($mode) {
58		// Lookahead assertion: check that there is an end tag.
59		$this->Lexer->addEntryPattern('<spoiler[^>\r\n]*?>(?=.*?</spoiler>)', $mode, 'plugin_spoiler');
60	}
61
62	function postConnect() {
63		$this->Lexer->addExitPattern('</spoiler>', 'plugin_spoiler');
64	}
65
66	function handle($match, $state, $pos, Doku_Handler $handler){
67		switch ($state) {
68			case DOKU_LEXER_ENTER :
69				// "<spoiler" options ">"
70				$options = substr($match, 7, -1);
71
72				$title = 'Spoiler';
73				if (strpos($options, '|') !== False) {
74					$title = substr($options, strpos($options, '|') + 1);
75				}
76
77				return array($state, $title);
78				break;
79			case DOKU_LEXER_MATCHED :
80				break;
81			case DOKU_LEXER_UNMATCHED :
82				return array($state, $match);
83				break;
84			case DOKU_LEXER_EXIT :
85				break;
86			case DOKU_LEXER_SPECIAL :
87				break;
88		}
89		return array($state);
90	}
91
92	function render($mode, Doku_Renderer $renderer, $data) {
93		if($mode == 'xhtml'){
94			list($state, $payload) = $data;
95
96			switch ($state) {
97				case DOKU_LEXER_ENTER :
98					$script = "c = this.parentNode.getElementsByTagName('div')[1]; if (this.value == 'Show') { c.style.display = ''; this.value = 'Hide' } else { c.style.display = 'none'; this.value = 'Show' }";
99					$renderer->doc .= '<div class="spoiler"><div class="title">'. $payload .'</div><input type="button" value="Show" onClick="'. $script .'" /><div class="content" style="display: none">';
100					// two open div tags
101					break;
102				case DOKU_LEXER_MATCHED :
103					break;
104				case DOKU_LEXER_UNMATCHED :
105					$renderer->doc .= $renderer->_xmlEntities($payload);
106					break;
107				case DOKU_LEXER_EXIT :
108					$renderer->doc .= '</div></div>';
109					break;
110			}
111
112			return true;
113		}
114		return false;
115	}
116}
117
118// VIM: ex: noet ts=4 sw=4 enc=utf-8 :
119