Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add macro TitleIndex #1602

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/moin/macros/ItemList.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright: 2019 MoinMoin:KentWatsen
# Copyright: 2024 MoinMoin:UlrichB
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

"""
Expand Down Expand Up @@ -67,7 +68,7 @@
from moin.i18n import _
from moin.utils.tree import moin_page
from moin.utils.interwiki import split_fqname
from moin.macros._base import MacroPageLinkListBase
from moin.macros._base import MacroPageLinkListBase, get_item_names


class Macro(MacroPageLinkListBase):
Expand Down Expand Up @@ -131,7 +132,7 @@ def macro(self, content, arguments, page_url, alternative):
return admonition

# process subitems
children = self.get_item_names(item, startswith=startswith, skiptag=skiptag)
children = get_item_names(item, startswith=startswith, skiptag=skiptag)
if regex:
try:
regex_re = re.compile(regex, re.IGNORECASE)
Expand Down
5 changes: 3 additions & 2 deletions src/moin/macros/RandomItem.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright: 2000 Juergen Hermann <[email protected]>
# Copyright: 2008-2011 MoinMoin:ThomasWaldmann
# Copyright: 2024 MoinMoin:UlrichB
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

"""
Expand All @@ -13,7 +14,7 @@
from moin.utils.iri import Iri
from moin.utils.tree import moin_page, xlink
from moin.items import Item
from moin.macros._base import MacroPageLinkListBase
from moin.macros._base import MacroPageLinkListBase, get_item_names
from moin.storage.middleware.protecting import AccessDenied

random.seed()
Expand All @@ -26,7 +27,7 @@ def macro(self, content, arguments, page_url, alternative):
else:
item_count = 1

all_item_names = self.get_item_names()
all_item_names = get_item_names()

# Now select random item from the full list, and if it exists and
# we can read it, save.
Expand Down
35 changes: 35 additions & 0 deletions src/moin/macros/TitleIndex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright: 2024 MoinMoin:UlrichB
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

"""
TitleIndex - generates a list of links for the namespace of the current item, grouped by initials

Parameters:
None

Usage:
<<TitleIndex>>
"""

from moin.macros._base import MacroMultiLinkListBase, get_item_names
from moin.i18n import _
from moin.utils.tree import moin_page
from moin.utils.interwiki import split_fqname


class Macro(MacroMultiLinkListBase):
def macro(self, content, arguments, page_url, alternative):
# get namespace of current item
namespace = split_fqname(str(page_url.path)).namespace

if arguments:
raise ValueError(_("TitleList macro does not have any arguments."))

children = get_item_names(namespace)
if not children:
empty_list = moin_page.list(attrib={moin_page.item_label_generate: 'unordered'})
item_body = moin_page.list_item_body(children=[_("<TitleList macro: No matching items were found.>")])
empty_list.append(moin_page.list_item(children=[item_body]))
return empty_list

return self.create_multi_pagelink_list(children, namespace)
150 changes: 111 additions & 39 deletions src/moin/macros/_base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright: 2008 MoinMoin:BastianBlank
# Copyright: 2024 MoinMoin:UlrichB
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

"""
Expand All @@ -15,6 +16,51 @@
from moin.constants.keys import TAGS


def get_item_names(name='', startswith='', kind='files', skiptag=''):
"""
For the specified item, return the fullname of matching descendents.

Input:

name: the name of the item to get. If '' is passed, then the
top-level item is used.

startwith: a substring the matching pages must begin with. If no
value is specified, then all pages are returned.

kind: the kind of page to return. Valid values include:

files: decendents that do not contain decendents. (default)
dirs: decendents that contain decendents.
both: both 'files' and 'dirs', with duplicates removed.

skiptag: skip items having this tag

Output:

A List of descendent items using their "fullname" value
"""
try:
item = Item.create(name)
except AccessDenied:
abort(403)
dirs, files = item.get_index(startswith)
item_names = []
if not kind or kind == "files" or kind == "both":
for item in files:
if skiptag and TAGS in item.meta and skiptag in item.meta[TAGS]:
continue
item_names.append(item.fullname)
if kind == "dirs" or kind == "both":
for item in dirs:
if skiptag and skiptag in item.meta[TAGS]:
continue
item_names.append(item.fullname)
if kind == "both":
item_names = list(set(item_names)) # remove duplicates
return item_names


class MacroBase:
"""
Macro base class.
Expand Down Expand Up @@ -96,10 +142,12 @@ def create_pagelink_list(self, pagenames, ordered=False, display="FullPath"):
uppercase character.
skiptag : skip items with this tag
ItemTitle : Use the title from the first header in the linked page *not implemented
"""
"""

page_list = moin_page.list(attrib={moin_page.item_label_generate: ordered and 'ordered' or 'unordered'})

for pagename in pagenames:

fqname = pagename.fullname
# This link can never reach pagelinks
url = str(iri.Iri(scheme='wiki', authority='', path='/' + fqname))
Expand Down Expand Up @@ -128,51 +176,75 @@ def create_pagelink_list(self, pagenames, ordered=False, display="FullPath"):
item_body = moin_page.list_item_body(children=[pagelink])
item = moin_page.list_item(children=[item_body])
page_list.append(item)
return page_list

def get_item_names(self, name='', startswith='', kind='files', skiptag=''):
"""
For the specified item, return the fullname of matching descendents.

Input:

name: the name of the item to get. If '' is passed, then the
top-level item is used.

startwith: a substring the matching pages must begin with. If no
value is specified, then all pages are returned.
return page_list

kind: the kind of page to return. Valid values include:

files: decendents that do not contain decendents. (default)
dirs: decendents that contain decendents.
both: both 'files' and 'dirs', with duplicates removed.
class MacroMultiLinkListBase(MacroBlockBase):
def create_multi_pagelink_list(self, itemnames, namespace):
""" Creates an ET with a list of itemlinks from a list of itemnames
grouped by initials.

skiptag: skip items having this tag
Parameters:

Output:
itemnames: a list of items, each being like a flask request.path[1:]

A List of descendent items using their "fullname" value
namespace: Namespace of items
"""
try:
item = Item.create(name)
except AccessDenied:
abort(403)
dirs, files = item.get_index(startswith)
item_names = []
if not kind or kind == "files" or kind == "both":
for item in files:
if skiptag and TAGS in item.meta and skiptag in item.meta[TAGS]:
continue
item_names.append(item.fullname)
if kind == "dirs" or kind == "both":
for item in dirs:
if skiptag and skiptag in item.meta[TAGS]:
continue
item_names.append(item.fullname)
if kind == "both":
item_names = list(set(item_names)) # remove duplicates
return item_names

result_body = []
initials_linklist = []
initial_letter = ' '

if namespace == '':
namespace_name = _("Namespace '%(name)s' ", name='default')
pos_namespace_cut = 0
else:
namespace_name = _("Namespace '%(name)s' ", name=namespace)
pos_namespace_cut = len(namespace) + 1

item_list = moin_page.list(attrib={moin_page.item_label_generate: 'unordered'})
initials_link = moin_page.a(attrib={xlink.href: '#idx-top'}, children=['top', ])
initials_linklist.extend([initials_link, moin_page.strong(children=[' | ', ])])

for itemname in itemnames:
if not itemname.value.startswith(initial_letter):
# generate header line with initial
initial_letter = itemname.value[0]
result_body.append(item_list) # finish item_list for last initial and initialize new item_list
item_list = moin_page.list(attrib={moin_page.item_label_generate: 'unordered'})

header_with_anchor = moin_page.span(
attrib={moin_page.class_: "moin-big", moin_page.id: 'idx-' + initial_letter},
children=[initial_letter,
moin_page.a(attrib={moin_page.class_: "moin-align-right", xlink.href: '#idx-top'},
children=['^', ])])
result_body.append(header_with_anchor)
initials_link = moin_page.a(attrib={xlink.href: '#idx-' + initial_letter}, children=[initial_letter])
initials_linklist.extend([initials_link, moin_page.strong(children=[' | ',])])

# build and add itemname link
fqname = itemname.fullname
url = str(iri.Iri(scheme='wiki', authority='', path='/' + fqname))
linkname = fqname[pos_namespace_cut:]
pagelink = moin_page.a(attrib={xlink.href: url}, children=[linkname])
item_body = moin_page.list_item_body(children=[pagelink])
item = moin_page.list_item(children=[item_body])
item_list.append(item)

result_body.append(item_list) # finish item_list for last initial

# Add a list of links for each used initial at top and bottom of the index
initials_begin = moin_page.span(attrib={moin_page.id: "idx-top", moin_page.class_: "moin-align-left"},
children=[_("Index of %(what)s", what=namespace_name), ])
initials_link_end = moin_page.a(attrib={xlink.href: '#idx-bottom'}, children=['bottom', ])
initials_linklist.append(initials_link_end)
initials_links_span = moin_page.span(attrib={moin_page.class_: "moin-align-right"}, children=initials_linklist)
result_body.insert(0, moin_page.p(children=[initials_begin, initials_links_span]))
initials_end = moin_page.span(
attrib={moin_page.id: "idx-bottom", moin_page.class_: "moin-align-left"}, children=".")
result_body.append(moin_page.p(children=[initials_end, initials_links_span]))
return moin_page.body(children=result_body)


class MacroNumberPageLinkListBase(MacroBlockBase):
Expand Down