1<?php
2
3
4// must be run within Dokuwiki
5use ComboStrap\CallStack;
6use ComboStrap\Dimension;
7use ComboStrap\PluginUtility;
8use ComboStrap\TagAttributes;
9
10if (!defined('DOKU_INC')) die();
11
12/**
13 * Class syntax_plugin_combo_text
14 * A text block that permits to style
15 * paragraph at once
16 *
17 * The output will be a series of {@link syntax_plugin_combo_para paragraph}
18 * with the same properties
19 *
20 * It permits to have several paragraph
21 */
22class syntax_plugin_combo_text extends DokuWiki_Syntax_Plugin
23{
24
25    const TAG = "text";
26    const TAGS = ["typo", self::TAG];
27
28    /**
29     * Syntax Type.
30     *
31     * Needs to return one of the mode types defined in {@link $PARSER_MODES} in parser.php
32     * @see DokuWiki_Syntax_Plugin::getType()
33     */
34    function getType(): string
35    {
36        return 'paragraphs';
37    }
38
39    /**
40     * How Dokuwiki will add P element
41     *
42     *  * 'normal' - The plugin can be used inside paragraphs
43     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
44     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
45     *
46     * @see DokuWiki_Syntax_Plugin::getPType()
47     */
48    function getPType(): string
49    {
50        return 'stack';
51    }
52
53    /**
54     * @return array
55     * Allow which kind of plugin inside
56     *
57     * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs')
58     * because we manage self the content and we call self the parser
59     *
60     * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php
61     */
62    function getAllowedTypes(): array
63    {
64        return array('formatting', 'substition', 'paragraphs');
65    }
66
67    public function accepts($mode): bool
68    {
69
70        return syntax_plugin_combo_preformatted::disablePreformatted($mode);
71
72    }
73
74
75    function getSort(): int
76    {
77        /**
78         * Less than {@link syntax_plugin_typography_base}
79         */
80        return 65;
81    }
82
83
84    function connectTo($mode)
85    {
86
87        foreach (self::TAGS as $tag) {
88            $pattern = PluginUtility::getContainerTagPattern($tag);
89            $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
90        }
91    }
92
93
94    function postConnect()
95    {
96        foreach (self::TAGS as $tag) {
97            $this->Lexer->addExitPattern('</' . $tag . '>', PluginUtility::getModeFromTag($this->getPluginComponent()));
98        }
99
100    }
101
102    function handle($match, $state, $pos, Doku_Handler $handler)
103    {
104
105        switch ($state) {
106
107            case DOKU_LEXER_ENTER :
108
109                $attributes = TagAttributes::createFromTagMatch($match);
110                $callStackArray = $attributes->toCallStackArray();
111
112                return array(
113                    PluginUtility::STATE => $state,
114                    PluginUtility::ATTRIBUTES => $callStackArray
115                );
116
117            case DOKU_LEXER_UNMATCHED :
118                return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler);
119
120            case DOKU_LEXER_EXIT :
121                /**
122                 * Transform all paragraphs
123                 * with the type as class
124                 */
125                $callStack = CallStack::createFromHandler($handler);
126                $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall();
127                $attributes = $openingCall->getAttributes();
128                // if there is no EOL, we add one to create at minimal a paragraph
129                $callStack->insertEolIfNextCallIsNotEolOrBlock();
130                $callStack->processEolToEndStack($attributes);
131
132                /**
133                 * Check and add a scroll toggle if the
134                 * text is constrained by height
135                 */
136                Dimension::addScrollToggleOnClickIfNoControl($callStack);
137
138                return array(PluginUtility::STATE => $state);
139
140
141        }
142        return array();
143
144    }
145
146    /**
147     * Render the output
148     * @param string $format
149     * @param Doku_Renderer $renderer
150     * @param array $data - what the function handle() return'ed
151     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
152     * @see DokuWiki_Syntax_Plugin::render()
153     *
154     *
155     */
156    function render($format, Doku_Renderer $renderer, $data): bool
157    {
158        if ($format == 'xhtml') {
159
160            /** @var Doku_Renderer_xhtml $renderer */
161            $state = $data[PluginUtility::STATE];
162            switch ($state) {
163                case DOKU_LEXER_EXIT :
164                case DOKU_LEXER_ENTER :
165                    /**
166                     * The {@link DOKU_LEXER_EXIT} of the {@link syntax_plugin_combo_text::handle()}
167                     * has already created in the callstack the {@link syntax_plugin_combo_para} call
168                     */
169                    $renderer->doc .= "";
170                    break;
171                case DOKU_LEXER_UNMATCHED :
172                    $renderer->doc .= PluginUtility::renderUnmatched($data);
173                    break;
174            }
175            return true;
176        }
177
178        // unsupported $mode
179        return false;
180    }
181
182
183}
184
185