sbrl / Pepperminty-Wiki

A wiki in a box
https://peppermint.mooncarrot.space/
Mozilla Public License 2.0
185 stars 22 forks source link

Feature Request: Enhance Sidebar #246

Open ElDani82 opened 1 year ago

ElDani82 commented 1 year ago

The sidebar will become bloated at some point, when the wiki accumulates too many pages and files. Not all of that should even be visible in the sidebar. The existing on/off and depth settings are a start, but I'd love to see two more to make the best use of the sidebar as a true navigation tool.

The extra option I'd love to see is a per-page setting. Optimally there would be two: one to hide a specific page from appearing in the sidebar (which also disregards all of its potential children) and two in order to show the specified page but hide all of its children.

I've found that tags are a quick and dirty way of implementing this feature. The tags are named sidebar_exclude_page and sidebar_exclude_children and this is the result:

image

The code of this hack is only applied to the render_sidebar function and has no impact on the wiki if the sidebar or the tags aren't used:

function render_sidebar($pageindex, $root_pagename = "", $depth = 0)
{
    global $settings;

    if($depth > $settings->sidebar_maxdepth)
        return null;

    if(mb_strlen($root_pagename) > 0) $root_pagename .= "/";

    $result = "<ul";
    // If this is the very root of the tree, add an extra class to it
    if($root_pagename == "") $result .= " class='sidebar-tree'";
    $result .=">";
    $subpages_added = 0;
    foreach ($pageindex as $pagename => $details)
    {
        // If we have a valid root pagename, and it isn't present at the
        // beginning of the current pagename, skip it
        if($root_pagename !== "" && strpos($pagename, $root_pagename) !== 0)
            continue;

        // Exclude page from appearing in the sidebar
        if(isset($details->tags) && in_array("sidebar_exclude_page", $details->tags))
            continue;

        // The current page is the same as the root page, skip it
        if($pagename == $root_pagename)
            continue;

        // If the page already appears on the sidebar, skip it
        if(strpos($result, ">$pagename<\a>") !== false)
            continue;

        $pagename_relative = substr($pagename, strlen($root_pagename));

        // If the part of the current pagename that comes after the root
        // pagename has a slash in it, skip it as it is a sub-sub page.
        if(strpos($pagename_relative, "/") !== false)
            continue;

        $subpage_sidebar = null;
        // Exclude children from appearing in the sidebar
        if(!isset($details->tags) || !in_array("sidebar_exclude_children", $details->tags))
            $subpage_sidebar = render_sidebar($pageindex, $pagename, $depth + 1);

        if($subpage_sidebar === null) {
            $result .= "<li><a href='?action=$settings->defaultaction&page=$pagename'>$pagename_relative</a></li>";
        }
        else {
            $result .= "<li><details open>
                <summary><a href='?action=$settings->defaultaction&page=$pagename'>$pagename_relative</a></summary>
                    $subpage_sidebar
                </details></li>\n";
        }
        $subpages_added++;
    }
    $result .= "</ul>\n";

    if($subpages_added === 0) return null;

    return $result == "<ul></ul>\n" ? "" : $result;
}

Edit: seems $details->tags isn't always available. Sometimes it's missing entirely, sometimes its content is an empty array when no tags are set on a page. Added sanity check for that.

This is sufficient for my purposes, but maybe something more elegant could be added to make the process more intuitive.