Skip to content

Commit

Permalink
Update TOC macro to enable feature parity with Article List (#1304)
Browse files Browse the repository at this point in the history
Fixes This is for Issue: #1042

Co-authored-by: Oscar Cortez <om.cortez.2010@gmail.com>
  • Loading branch information
orcephrye and oscarmcm committed Oct 2, 2023
1 parent 6dccf64 commit 22dc9eb
Show file tree
Hide file tree
Showing 3 changed files with 406 additions and 7 deletions.
38 changes: 34 additions & 4 deletions src/wiki/plugins/macros/mdx/macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.utils.translation import gettext as _
from wiki.core.markdown import add_to_registry
from wiki.plugins.macros import settings
from wiki.plugins.macros.mdx import toc

# See:
# http://stackoverflow.com/questions/430759/regex-for-managing-escaped-characters-for-items-like-string-literals
Expand Down Expand Up @@ -40,7 +41,7 @@ def __init__(self, pattern, md=None):
)

def handleMatch(self, m):
macro = m.group("macro").strip()
macro = m.group("macro").strip().lower()
if macro not in settings.METHODS or not hasattr(self, macro):
return m.group(2)

Expand Down Expand Up @@ -83,14 +84,43 @@ def article_list(self, depth="2"):
"args": {"depth": _("Maximum depth to show levels for.")},
}

def toc(self):
def toc(self, **kwargs):
toc.WikiTreeProcessorClass.CACHED_KWARGS = kwargs
return "[TOC]"

toc.meta = {
"short_description": _("Table of contents"),
"help_text": _("Insert a table of contents matching the headings."),
"example_code": "[TOC]",
"args": {},
"example_code": "[TOC] or [TOC toc_depth:1]",
"args": {
"title": _(
"Title to insert in the Table of Contents’ <div>. Defaults to Contents."
),
"baselevel": _("Base level for headers. Defaults to 1."),
"separator": _(
"Word separator. Character which replaces white space in id. Defaults to “-”."
),
"anchorlink": _(
"Set to True to cause all headers to link to themselves. Default is False."
),
"anchorlink_class": _(
"CSS class(es) used for the link. Defaults to toclink."
),
"permalink": _(
"Set to True or a string to generate permanent links at the end of each header. Useful with Sphinx style sheets."
),
"permalink_class": _(
"CSS class(es) used for the link. Defaults to headerlink."
),
"permalink_title": _(
"Title attribute of the permanent link. Defaults to Permanent link."
),
"toc_depth": _(
"Define the range of section levels to include in the Table of Contents. A single integer (b) defines the bottom section "
"level (<h1>..<hb>) only. A string consisting of two digits separated by a hyphen in between ('2-5'), define the top (t) "
"and the bottom (b) (<ht>..<hb>). Defaults to 6 (bottom)."
),
},
}

def wikilink(self):
Expand Down
93 changes: 92 additions & 1 deletion src/wiki/plugins/macros/mdx/toc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,107 @@
HEADER_ID_PREFIX = "wiki-toc-"


def process_toc_depth(toc_depth):
if isinstance(toc_depth, str) and "-" in toc_depth:
toc_top, toc_bottom = [int(x) for x in toc_depth.split("-")]
else:
toc_top = 1
toc_bottom = int(toc_depth)
return {"toc_top": toc_top, "toc_bottom": toc_bottom}


def process_bool_value(bool_val, org_val):
if bool_val.lower() == "false" or bool_val == "0":
return False
elif bool_val.lower() == "true" or bool_val == "1":
return True
else:
return org_val


def process_value(org_val, new_val):
try:
if type(new_val) is str:
new_val = new_val.lstrip("'").rstrip("'")

if type(org_val) is bool:
return process_bool_value(new_val, org_val)
elif type(org_val) is int:
return int(new_val)
elif type(org_val) is str:
return new_val
else:
return org_val
except Exception:
return org_val


def wiki_slugify(*args, **kwargs):
return HEADER_ID_PREFIX + slugify(*args, **kwargs)


class WikiTreeProcessorClass(TocTreeprocessor):
CACHED_KWARGS = dict() # Used to cache arguments parsed by the MacroPattern
# Used to map the keyword arguments to the Class Objects attribute name.
TOC_CONFIG_VALUES = {
"title": "title",
"baselevel": "base_level",
"separator": "sep",
"anchorlink": "use_anchors",
"anchorlink_class": "anchorlink_class",
"permalink": "use_permalinks",
"permalink_class": "permalink_class",
"permalink_title": "permalink_title",
"toc_depth": process_toc_depth,
"toc_top": "toc_top",
"toc_bottom": "toc_bottom",
}

def run(self, doc):
# Necessary because self.title is set to a LazyObject via gettext_lazy
if self.title:
self.title = str(self.title)
super().run(doc)

tmp_kwargs = dict()

def _helper_swap_values(key, value):
# Saves the existing attribute value to a dictionary
tmp_kwargs[WikiTreeProcessorClass.TOC_CONFIG_VALUES[key]] = getattr(
self, WikiTreeProcessorClass.TOC_CONFIG_VALUES[key]
)
# This sets the value to a TocTreeprocessor attribute of its corresponding name
setattr(
self,
WikiTreeProcessorClass.TOC_CONFIG_VALUES[key],
process_value(
tmp_kwargs[WikiTreeProcessorClass.TOC_CONFIG_VALUES[key]],
value,
),
)

try:
# Iterator through CACHED_KWARGS to set attributes values and save defaults attribute values to tmp_kwargs
for k, v in WikiTreeProcessorClass.CACHED_KWARGS.items():
if (
k in WikiTreeProcessorClass.TOC_CONFIG_VALUES
): # Map of keyword names to their respected object attribute names
if callable(
WikiTreeProcessorClass.TOC_CONFIG_VALUES[k]
): # Some values in the dictionary are functions to further process values
for tock, tocv in WikiTreeProcessorClass.TOC_CONFIG_VALUES[k](
v
).items():
_helper_swap_values(tock, tocv)
else:
_helper_swap_values(k, v)
super().run(doc)
finally:
# Use tmp to reset values
for k, v in tmp_kwargs.items():
if hasattr(self, k):
setattr(self, k, v)
# Unset cached kwargs
WikiTreeProcessorClass.CACHED_KWARGS = dict()


class WikiTocExtension(TocExtension):
Expand Down

0 comments on commit 22dc9eb

Please sign in to comment.