1<?php
2if (!defined('DOKU_INC')) die(); /* must be run from within DokuWiki */
3
4
5//Library of template function
6require_once(__DIR__ . '/class/TplUtility.php');
7
8use Combostrap\TplUtility;
9use dokuwiki\Extension\Event;
10
11
12global $ID;
13global $lang;
14global $ACT;
15global $conf;
16
17
18/**
19 * The Content first because it contains
20 * also the front matter that may influence the other bars
21 *
22 * If the do action is edit, php plugin uses echo
23 * a lot and the buffer is too small, we got then a buffer overflow
24 *
25 * Other action takes place further where the content should be
26 */
27$mainHtml = "";
28if ($ACT === 'show') {
29    $mainHtml = TplUtility::tpl_content($prependTOC = false);
30}
31
32/**
33 * Sidebar
34 */
35$sidebarName = TplUtility::getSideSlotPageName();
36
37$nearestSidebar = page_findnearest($sidebarName);
38$showSideBar = $nearestSidebar !== false && ($ACT === 'show');
39if ($showSideBar) {
40    /**
41     * Even if there is no sidebar
42     * the rendering may output
43     * debug information in the form of
44     * an HTML comment
45     */
46    $sideBarHtml = TplUtility::renderSlot($nearestSidebar);
47}
48
49
50/**
51 * Sidekickbar
52 */
53$sideKickPageName = TplUtility::getSideKickSlotPageName();
54$hasRightSidebar = page_findnearest($sideKickPageName);
55$showSideKickBar = $hasRightSidebar && ($ACT == 'show');
56if ($showSideKickBar) {
57    $sideKickBarHtml = TplUtility::renderSlot($sideKickPageName);
58}
59
60/**
61 * Main header and footer
62 */
63$nearestMainHeader = page_findnearest(TplUtility::SLOT_MAIN_HEADER_NAME);
64$showMainHeader = $nearestMainHeader !== false
65    && ($ACT === 'show')
66    && TplUtility::isNotSlot()
67    && TplUtility::isNotRootHome();
68if ($showMainHeader !== false) {
69    $mainHeaderHtml = TplUtility::renderSlot($nearestMainHeader);
70}
71
72$nearestMainFooter = page_findnearest(TplUtility::SLOT_MAIN_FOOTER_NAME);
73$showMainFooter = $nearestMainFooter !== false
74    && ($ACT === 'show')
75    && TplUtility::isNotSlot()
76    && TplUtility::isNotRootHome();
77if ($showMainFooter !== false) {
78    $mainFooterHtml = TplUtility::renderSlot($nearestMainFooter);
79}
80
81
82/**
83 * Headerbar
84 */
85$headerBar = TplUtility::getPageHeader();
86
87/**
88 * Footerbar
89 */
90$footerBar = TplUtility::getFooter();
91
92
93/**
94 * Grid
95 */
96$gridColumns = tpl_getConf(TplUtility::CONF_GRID_COLUMNS);
97/**
98 * Layout
99 *
100 * See also: https://1linelayouts.glitch.me/ and https://www.cssportal.com/layout-generator/layout.php
101 *
102 * Two basic layouts for the web: fixed or liquid
103 * A liquid design (also referred to as a fluid or dynamic design) fills the entire browser window by using percentages
104 * rather than fixed pixel values to define the width / height
105 *
106 * dimension =
107 *   "fluid" = max-width / min-height
108 *   "contained" =
109 *
110 * In fluid web design, the widths of page elements are set proportional to the width of the screen or browser window.
111 * A fluid website expands or contracts based on the width of the current viewport.
112 *
113 * Contained (ie fixed)
114 * https://getbootstrap.com/docs/5.0/layout/containers/
115 *
116 */
117// for the identity forms
118global $ACT;
119if (in_array($ACT, ["login", "resendpwd", "register", "profile"])) {
120    $layout = "median";
121} else {
122    $layout = p_get_metadata($ID, "layout");
123}
124if ($layout === "median") {
125    $maximalWidthMain = 8;
126} else {
127    $maximalWidthMain = $gridColumns;
128}
129$sidebarScale = 3;
130$sideKickBarScale = 3;
131
132switch ($ACT) {
133    case "show":
134        if ($showSideBar) {
135            $mainGridScale = $showSideKickBar ? $gridColumns - $sidebarScale - $sideKickBarScale : $gridColumns - $sidebarScale;
136        } else {
137            $mainGridScale = $showSideKickBar ? $gridColumns - $sideKickBarScale : $maximalWidthMain;
138        }
139        break;
140    default:
141        $mainGridScale = $gridColumns;
142}
143
144
145/**
146 * Landing page
147 */
148$landingPageGutter = "";
149$mainIsContained = true;
150if ($ACT != "show") {
151    $mainIsContained = true;
152} else {
153    if ($layout == "landing") {
154        $mainIsContained = false;
155        // No gutter on x otherwise there is a overflow on the right
156        $landingPageGutter = "style=\"--bs-gutter-x: 0\"";
157    }
158}
159$mainContainedClasses = "";
160if ($mainIsContained) {
161    $mainContainedClasses = "container mb-3";
162}
163
164/**
165 * Bootstrap meta-headers
166 */
167TplUtility::registerHeaderHandler();
168
169/**
170 * Default rem font size
171 */
172$rootStyle = "";
173$htmlRem = TplUtility::getRem();
174if ($htmlRem != null) {
175    $rootStyle = "style=\"font-size:{$htmlRem}px\"";
176}
177
178/**
179 * Railbar
180 * Railbar can add snippet in the head
181 * And should then be could before the HTML output
182 */
183$railBar = TplUtility::getRailBar();
184
185/**
186 * The output buffer should be empty on show
187 * and can be not empty on other do action
188 */
189$outputBuffer = TplUtility::outputBuffer();
190
191
192?>
193
194<?php // DocType Required: https://getbootstrap.com/docs/5.0/getting-started/introduction/#html5-doctype ?>
195<!DOCTYPE html >
196<?php
197/**
198 * Lang for a page
199 *
200 * https://www.w3.org/International/questions/qa-html-language-declarations
201 *   * Always use a language attribute on the html element.
202 *   * When serving XHTML 1.x (ie. using a MIME type such as application/xhtml+xml),
203 * use both the lang attribute and the xml:lang attribute together
204 *
205 * See also {@link \ComboStrap\Lang::processLangAttribute()} for the localization of an element
206 *
207 * @var $javascriptRTL - put the button to the end when the page has a language direction of rtl
208 */
209$javascriptRTL = "";
210if ($lang['direction'] == "rtl") {
211    $javascriptRTL = <<<EOF
212<script>
213document.addEventListener('DOMContentLoaded', () => {
214    Array.from(document.getElementsByClassName("secedit")).forEach(e=>e.classList.add('float-end'));
215    }
216);
217</script>
218EOF;
219
220}
221?>
222<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $conf['lang'] ?>" lang="<?php echo $conf['lang'] ?>"
223      dir="<?php echo $lang['direction'] ?>" <?php echo $rootStyle ?>>
224<head>
225
226    <?php // Avoid using character entities in your HTML, provided their encoding matches that of the document (generally UTF-8) ?>
227    <meta charset="utf-8"/>
228
229    <?php // Responsive meta tag ?>
230    <meta name="viewport" content="width=device-width,initial-scale=1"/>
231
232    <?php // Headers ?>
233    <?php tpl_metaheaders() ?>
234
235    <title><?php TplUtility::renderPageTitle() ?></title>
236
237    <?php // Favicon ?>
238    <?php echo TplUtility::renderFaviconMetaLinks() ?>
239
240    <?php
241    /**
242     * In case of a RTL lang,
243     * we put the secedit button to the left
244     */
245    echo $javascriptRTL;
246    ?>
247
248    <?php
249    /**
250     * When we have a landing page, the railbar
251     * which is by default on the right side is not visible
252     * This setting will set up inside and make it visible alongside the page
253     * We may also just put it completely in the offcanvas
254     * See for the HTML code {@link TplUtility::getRailBar()}
255     */
256    if ($layout == "landing" & $ACT == "show") { ?>
257        <style>
258            #railbar-fixed {
259                right: 44px !important;
260            }
261        </style>
262    <?php }
263    // slot-combo is relative to position the edit button
264    ?>
265    <style>
266        .slot-combo {
267            position: relative;
268        }
269    </style>
270
271</head>
272<?php
273// * tpl_classes will add the dokuwiki class. See https://www.dokuwiki.org/devel:templates#dokuwiki_class
274// * dokuwiki__top ID is needed for the "Back to top" utility
275// * used also by some plugins
276?>
277<body class="dokuwiki">
278
279<?php
280echo $headerBar
281
282// Relative positioning is important for the positioning of the pagetools
283?>
284<div class="<?php echo $mainContainedClasses ?> <?php echo tpl_classes() ?> " style="position: relative">
285
286
287    <?php // To go at the top of the page, style is for the fix top page --> ?>
288    <div id="dokuwiki__top"></div>
289
290
291    <?php
292    // The global message array
293    html_msgarea()
294    ?>
295
296
297    <?php
298    //  A trigger to show content on the top part of the website
299    $data = "";// Mandatory
300    Event::createAndTrigger('TPL_PAGE_TOP_OUTPUT', $data);
301    ?>
302
303
304    <div class="row justify-content-md-center" <?php echo($landingPageGutter) ?>>
305
306
307        <?php if ($ACT === "show") { ?>
308
309            <?php
310            // SIDE BAR
311            if ($showSideBar): ?>
312                <div role="complementary"
313                     class="slot-combo col-md-<?php echo($sidebarScale) ?> order-last order-md-first d-print-none">
314
315                    <?php echo $sideBarHtml ?>
316
317                </div>
318            <?php endif; ?>
319
320            <main class="col-md-<?php echo($mainGridScale) ?> order-first">
321
322                <?php if ($showMainHeader) { ?>
323                    <div id="main-header" class="slot-combo">
324                        <?php echo $mainHeaderHtml; ?>
325                    </div>
326                <?php }
327                // Add a p around the content to enable the reader view in Mozilla
328                // https://github.com/mozilla/readability
329                // But Firefox close the P because they must contain only inline element ???
330                echo $outputBuffer;
331
332                echo $mainHtml;
333                if ($showMainFooter) { ?>
334                    <div id="main-footer" class="slot-combo">
335                        <?php echo $mainFooterHtml; ?>
336                    </div>
337                <?php }
338                ?>
339            </main>
340
341            <?php if ($showSideKickBar):  // Sidekick bar  ?>
342
343                <div role="complementary"
344                     class="col-md-<?php echo($sideKickBarScale) ?> slot-combo order-xs-2 order-md-last d-print-none">
345
346                    <?php
347                    tpl_flush();
348
349                    echo $sideKickBarHtml;
350
351                    // A trigger to show content on the sidebar part of the website
352                    $data = "";// Mandatory
353                    Event::createAndTrigger('TPL_SIDEBAR_BOTTOM_OUTPUT', $data);
354                    ?>
355
356                </div>
357            <?php endif;  // end show content?>
358
359        <?php } else { // do not use the main html element for do/admin content, main is reserved for the styling of the page content ?>
360            <main class="col-md-<?php echo($mainGridScale) ?>">
361                <?php
362                // all other action are using the php buffer
363                // we can then have an overflow
364                // the buffer is flushed
365                // this is why we output the content of do page here
366                echo TplUtility::tpl_content($prependTOC = true);
367                ?>
368            </main>
369        <?php } ?>
370
371    </div>
372
373    <?php echo $railBar ?>
374
375</div>
376
377
378<?php
379// Footer
380echo $footerBar;
381// Powered By
382echo TplUtility::getPoweredBy();
383// The stylesheet (before indexer work and script at the end)
384TplUtility::addPreloadedResources();
385?>
386
387
388<div class="d-none">
389    <?php
390    // Indexer (Background tasks)
391    tpl_indexerWebBug()
392    ?>
393</div>
394
395</body>
396</html>
397