' . PHP_EOL; // Try to get the template custom breadcrumb $breadCrumb = tpl_getLang('breadcrumb'); if ($breadCrumb == '') { // If not present for the language, get the default one $breadCrumb = $lang['breadcrumb']; } echo '' . $breadCrumb . ': '; foreach ($crumbs as $id => $name) { $i++; if ($i == $last) { print '' . PHP_EOL; } echo '' . PHP_EOL; return true; } /** * Hierarchical breadcrumbs * * This will return the Hierarchical breadcrumbs. * * Config: * - $conf['youarehere'] must be true * - add $lang['youarehere'] if $printPrefix is true * * @param bool $printPrefix print or not the $lang['youarehere'] * @return string */ function tpl_youarehere_bootstrap($printPrefix = false) { global $conf; global $lang; // check if enabled if (!$conf['youarehere']) return; // print intermediate namespace links $htmlOutput = ''.PHP_EOL; // return true; // } // // skipping for namespace index // $page = $idPart.$idParts[$i]; // if($page == $conf['start']) { // echo ''.PHP_EOL; // return true; // } // print current page // print '
  • '; // tpl_link(wl($page), tpl_pagetitle($page,true), 'title="' . $page . '"'); $htmlOutput .= '
  • ' . PHP_EOL; // close the breadcrumb $htmlOutput .= '' . PHP_EOL; return $htmlOutput; } /* * Function return the page name from an id * @author Nicolas GERARD * * @param string $sep Separator between entries * @return bool */ function tpl_pageName($id) { // page names $name = noNSorNS($id); if (useHeading('navigation')) { // get page title $title = p_get_first_heading($id, METADATA_RENDER_USING_SIMPLE_CACHE); if ($title) { $name = $title; } } return $name; } function tpl_searchform_bootie($ajax = true, $autocomplete = true) { global $lang; global $ACT; global $QUERY; // don't print the search form if search action has been disabled if (!actionOK('search')) return false; print ''; return true; } /** * This is a fork of tpl_actionlink where I have added the class parameters * * Like the action buttons but links * * @author Adrian Lang * @see tpl_get_action * * @param string $type action command * @param string $pre prefix of link * @param string $suf suffix of link * @param string $inner innerHML of link * @param bool $return if true it returns html, otherwise prints * @param string $class the class to be added * @return bool|string html or false if no data, true if printed */ function tpl_actionlink_bootie($type, $class = '', $pre = '', $suf = '', $inner = '', $return = false) { global $lang; $data = tpl_get_action($type); if ($data === false) { return false; } elseif (!is_array($data)) { $out = sprintf($data, 'link'); } else { /** * @var string $accesskey * @var string $id * @var string $method * @var bool $nofollow * @var array $params * @var string $replacement */ extract($data); if (strpos($id, '#') === 0) { $linktarget = $id; } else { $linktarget = wl($id, $params); } $caption = $lang['btn_' . $type]; if (strpos($caption, '%s')) { $caption = sprintf($caption, $replacement); } $akey = $addTitle = ''; if ($accesskey) { $akey = 'accesskey="' . $accesskey . '" '; $addTitle = ' [' . strtoupper($accesskey) . ']'; } $rel = $nofollow ? 'rel="nofollow" ' : ''; $out = $pre . tpl_link( $linktarget, (($inner) ? $inner : $caption), 'class="nav-link action ' . $type . ' ' . $class . '" ' . $akey . $rel . 'title="' . hsc($caption) . $addTitle . '"', true ) . $suf; } if ($return) return $out; echo $out; return true; } /** * @return array * Return the headers needed by this template * */ function tpl_get_default_headers() { $useCdn = tpl_getConf('cdn'); $script = array(); if (!$useCdn) { $localBaseJs = DOKU_BASE . 'lib/tpl/bootie/js/'; // Other mode, we pick the Javascript of Dokuwiki // jquery must not be slim because the post is needed for qsearch $script['jquery'] = array( 'src' => $localBaseJs . 'jquery-3.3.1.min.js', 'integrity' => "sha256-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT", 'crossorigin' => "anonymous", 'defer' => "true" ); $script['popper'] = array( 'src' => $localBaseJs . 'popper-1.14.7.min.js', 'integrity' => "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1", 'crossorigin' => "anonymous", 'defer' => "true" ); $script['bootstrap'] = array( 'src' => $localBaseJs . 'bootstrap-4.3.1.min.js', 'integrity' => "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM", 'crossorigin' => "anonymous", 'defer' => "true" ); } else { // use a cdn // jquery must not be slim because the post is needed for qsearch $script['jquery'] = array( 'src' => 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js', 'integrity' => "sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=", 'crossorigin' => "anonymous", 'defer' => "true" ); $script['popper'] = array( 'src' => 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js', 'integrity' => "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1", 'crossorigin' => "anonymous", 'defer' => "true" ); $script['bootstrap'] = array( 'src' => 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js', 'integrity' => "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM", 'crossorigin' => "anonymous", 'defer' => "true" ); } if (!$useCdn) { $baseCss = DOKU_BASE . 'lib/tpl/bootie/css/'; $css['bootstrap'] = array( 'href' => $baseCss . 'bootstrap-4.3.1.min.css', 'integrity' => "sha384-ZYfZnVukOuh/gRpU9uN+T9XwwRFJ9Y+0Ylk3zKvI184omb/HoOtQ0F8Iol7Nix7q", 'crossorigin' => "anonymous", 'rel' => "stylesheet", ); } else { $css['bootstrap'] = array( 'href' => 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css', 'integrity' => "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", 'crossorigin' => "anonymous", 'rel' => "stylesheet", ); }; return array( 'script' => $script, 'link' => $css ); } /** * @param Doku_Event $event * @param $param * Function that handle the META HEADER event * * It will add the Bootstrap Js and CSS * * Make all script and resources defer */ function tpl_bootie_meta_header(Doku_Event &$event, $param) { global $DOKU_TPL_BOOTIE_PRELOAD_CSS; $DOKU_TPL_BOOTIE_PRELOAD_CSS = array(); $newHeaderTypes = array(); $bootstrapHeaders = tpl_get_default_headers(); $eventHeaderTypes = $event->data; foreach ($eventHeaderTypes as $headerType => $headerData) { switch ($headerType) { case "meta": // generator, color, robots, keywords // nothing to do pick them all $newHeaderTypes[$headerType] = $headerData; break; case "link": // index, rss, manifest, search, alternate, stylesheet // delete edit $newLinkData = $bootstrapHeaders[$headerType]; // Css of Bootstrap will be unchanged foreach ($headerData as $linkData) { switch ($linkData['rel']) { case 'edit': break; case 'stylesheet': // Take the stylesheet to load them at the end $DOKU_TPL_BOOTIE_PRELOAD_CSS[] = $linkData; // Change the loading mechanism to preload $linkData['rel'] = 'preload'; $linkData['as'] = 'style'; $newLinkData[] = $linkData; break; default: $newLinkData[] = $linkData; break; } } $newHeaderTypes[$headerType] = $newLinkData; break; case "script": $newScriptData = array(); foreach ($headerData as $scriptData) { $scriptData['defer'] = "true"; $pos = strpos($scriptData['src'], 'jquery'); if ($pos === false) { $newScriptData[] = $scriptData; } else { // This is the Jquery script if (empty($_SERVER['REMOTE_USER'])) { // https://www.dokuwiki.org/config:jquerycdn // We take the Jquery of Bootstrap $newScriptData = array_merge($newScriptData, $bootstrapHeaders[$headerType]); } else { // We take the Jquery of doku and we add Bootstrap $newScriptData[] = $scriptData; // js $newScriptData[] = $bootstrapHeaders[$headerType]['popper']; $newScriptData[] = $bootstrapHeaders[$headerType]['bootstrap']; } } } $newHeaderTypes[$headerType] = $newScriptData; break; } } $event->data = $newHeaderTypes; }