xref: /plugin/combo/syntax/label.php (revision c3437056399326d621a01da73b649707fbb0ae69)
1<?php
2
3// implementation of
4// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite
5
6// must be run within Dokuwiki
7use ComboStrap\Bootstrap;
8use ComboStrap\CallStack;
9use ComboStrap\MediaLink;
10use ComboStrap\LogUtility;
11use ComboStrap\PluginUtility;
12use ComboStrap\Tag;
13use ComboStrap\TagAttributes;
14
15
16require_once(__DIR__ . '/../ComboStrap/HeaderUtility.php');
17
18if (!defined('DOKU_INC')) die();
19
20
21class syntax_plugin_combo_label extends DokuWiki_Syntax_Plugin
22{
23
24
25    const TAG = "label";
26
27    /**
28     * The id of the heading element for a accordion label
29     */
30    const HEADING_ID = "headingId";
31    /**
32     * The id of the collapsable target
33     */
34    const TARGET_ID = "targetId";
35
36    /**
37     * An indicator attribute that tells if the accordion is collpased or not
38     */
39    const COLLAPSED = "collapsed";
40
41    function getType()
42    {
43        return 'formatting';
44    }
45
46    /**
47     * How Dokuwiki will add P element
48     *
49     *  * 'normal' - The plugin can be used inside paragraphs (inline)
50     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
51     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
52     *
53     * @see DokuWiki_Syntax_Plugin::getPType()
54     */
55    function getPType()
56    {
57        return 'block';
58    }
59
60    function getAllowedTypes()
61    {
62        return array('substition', 'formatting', 'disabled');
63    }
64
65    function getSort()
66    {
67        return 201;
68    }
69
70
71    function connectTo($mode)
72    {
73
74        $this->Lexer->addEntryPattern(PluginUtility::getContainerTagPattern(self::TAG), $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
75    }
76
77    public function postConnect()
78    {
79        $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeFromTag($this->getPluginComponent()));
80    }
81
82    function handle($match, $state, $pos, Doku_Handler $handler)
83    {
84
85        switch ($state) {
86
87            case DOKU_LEXER_ENTER:
88                $tagAttributes = PluginUtility::getTagAttributes($match);
89
90                $tag = new Tag(self::TAG, $tagAttributes, $state, $handler);
91                $parentTag = $tag->getParent();
92                $context = null;
93                if ($parentTag != null) {
94                    $grandfather = $parentTag->getParent();
95                    if ($grandfather != null) {
96                        $grandFatherName = $grandfather->getName();
97                        switch ($grandFatherName) {
98                            case syntax_plugin_combo_accordion::TAG:
99                                $id = $parentTag->getAttribute("id");
100                                $tagAttributes["id"] = $id;
101                                $tagAttributes[self::HEADING_ID] = "heading" . ucfirst($id);
102                                $tagAttributes[self::TARGET_ID] = "collapse" . ucfirst($id);
103                                $parentAttribute = $parentTag->getAttributes();
104                                if (!key_exists(self::COLLAPSED, $parentAttribute)) {
105                                    // Accordion are collapsed by default
106                                    $tagAttributes[self::COLLAPSED] = "true";
107                                } else {
108                                    $tagAttributes[self::COLLAPSED] = $parentAttribute[self::COLLAPSED];
109                                }
110                                $context = syntax_plugin_combo_accordion::TAG;
111                                break;
112                            case  syntax_plugin_combo_tabs::TAG:
113                                $context = syntax_plugin_combo_tabs::TAG;
114                                $tagAttributes = $parentTag->getAttributes();
115                                break;
116                            default:
117                                LogUtility::log2FrontEnd("The label is included in the $grandFatherName component and this is unexpected", LogUtility::LVL_MSG_WARNING, self::TAG);
118                        }
119                    } else {
120                        /**
121                         * An panel may render alone in preview
122                         */
123                        if ($parentTag->getContext() == syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE) {
124                            $context = syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE;
125                        }
126                    }
127                }
128
129                return array(
130                    PluginUtility::STATE => $state,
131                    PluginUtility::ATTRIBUTES => $tagAttributes,
132                    PluginUtility::CONTEXT => $context
133                );
134
135            case DOKU_LEXER_UNMATCHED :
136                return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler);
137
138            case DOKU_LEXER_EXIT :
139                $callStack = CallStack::createFromHandler($handler);
140                $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall();
141                $context = $openingTag->getContext();
142
143                /**
144                 * An image in a label should have no link (ie no anchor)
145                 * because a anchor is used for navigation
146                 */
147                $callStack->processNoLinkOnImageToEndStack();
148
149                $callStack->closeAndResetPointer();
150
151
152                return array(
153                    PluginUtility::STATE => $state,
154                    PluginUtility::CONTEXT => $context,
155                    PluginUtility::ATTRIBUTES => $openingTag->getAttributes()
156                );
157
158
159        }
160        return array();
161
162    }
163
164    /**
165     * Render the output
166     * @param string $format
167     * @param Doku_Renderer $renderer
168     * @param array $data - what the function handle() return'ed
169     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
170     * @see DokuWiki_Syntax_Plugin::render()
171     *
172     *
173     */
174    function render($format, Doku_Renderer $renderer, $data)
175    {
176
177        if ($format == 'xhtml') {
178
179            /** @var Doku_Renderer_xhtml $renderer */
180            $state = $data[PluginUtility::STATE];
181            switch ($state) {
182
183                case DOKU_LEXER_ENTER:
184
185                    $context = $data[PluginUtility::CONTEXT];
186                    switch ($context) {
187                        case syntax_plugin_combo_accordion::TAG:
188                            $attribute = $data[PluginUtility::ATTRIBUTES];
189                            $headingId = $attribute[self::HEADING_ID];
190                            $collapseId = $attribute[self::TARGET_ID];
191                            $collapsed = $attribute[self::COLLAPSED];
192                            if ($collapsed == "false") {
193                                $collapsedClass = "collapsed";
194                            } else {
195                                $collapsedClass = "";
196                            }
197                            $renderer->doc .= "<div class=\"card-header\" id=\"$headingId\">" . DOKU_LF;
198                            $renderer->doc .= "<h2 class=\"mb-0\">";
199                            $dataNamespace = Bootstrap::getDataNamespace();
200                            $renderer->doc .= "<button class=\"btn btn-link btn-block text-left $collapsedClass\" type=\"button\" data{$dataNamespace}-toggle=\"collapse\" data{$dataNamespace}-target=\"#$collapseId\" aria-expanded=\"true\" aria-controls=\"$collapseId\">";
201                            break;
202                        case syntax_plugin_combo_tabs::TAG:
203                            $attributes = $data[PluginUtility::ATTRIBUTES];
204                            $renderer->doc .= syntax_plugin_combo_tabs::openNavigationalTabElement($attributes);
205                            break;
206                        case syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE:
207                            $attributes = syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE_ATTRIBUTES;
208                            $renderer->doc .= "<ul style=\"list-style-type: none;padding-inline-start: 0;\">";
209                            $renderer->doc .= syntax_plugin_combo_tabs::openNavigationalTabElement($attributes);
210                            break;
211                        default:
212                            LogUtility::log2FrontEnd("The context ($context) of the label is unknown in enter", LogUtility::LVL_MSG_WARNING, self::TAG);
213
214                    }
215                    break;
216
217                case DOKU_LEXER_UNMATCHED :
218                    $renderer->doc .= PluginUtility::renderUnmatched($data);
219                    break;
220
221                case DOKU_LEXER_EXIT:
222                    $context = $data[PluginUtility::CONTEXT];
223                    switch ($context) {
224                        case syntax_plugin_combo_accordion::TAG:
225                            $attribute = $data[PluginUtility::ATTRIBUTES];
226                            $collapseId = $attribute[self::TARGET_ID];
227                            $headingId = $attribute[self::HEADING_ID];
228                            $collapsed = $attribute[self::COLLAPSED];
229                            if ($collapsed == "false") {
230                                $showClass = "show";
231                            } else {
232                                $showClass = "";
233                            }
234                            $renderer->doc .= "</button></h2></div>";
235                            $dataNamespace = Bootstrap::getDataNamespace();
236                            $renderer->doc .= "<div id=\"$collapseId\" class=\"collapse $showClass\" aria-labelledby=\"$headingId\" data-{$dataNamespace}parent=\"#$headingId\">";
237                            $renderer->doc .= "<div class=\"card-body\">" . DOKU_LF;
238                            break;
239                        case syntax_plugin_combo_tabs::TAG:
240                            $renderer->doc .= syntax_plugin_combo_tabs::closeNavigationalTabElement();
241                            break;
242                        case syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE:
243                            $renderer->doc .= syntax_plugin_combo_tabs::closeNavigationalTabElement();
244                            $renderer->doc .= "</ul>";
245                            break;
246                        default:
247                            LogUtility::log2FrontEnd("The context ($context) of the label is unknown in exit", LogUtility::LVL_MSG_WARNING, self::TAG);
248
249
250                    }
251                    break;
252
253
254            }
255        }
256        // unsupported $mode
257        return false;
258    }
259
260
261}
262
263