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 RandomQuote macro #1789

Merged
merged 1 commit into from
Oct 31, 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
3 changes: 3 additions & 0 deletions docs/user/moinwiki.rst
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,9 @@ extra features. The following is a table of MoinMoin's macros.
+-------------------------------------------+------------------------------------------------------------+
| ``<<RandomItem(3)>>`` | Inserts names of 3 random items |
+-------------------------------------------+------------------------------------------------------------+
| ``<<RandomQuote(Itemname)>>`` | Select a random quote from the given item, |
| | or from FortuneCookies if omitted. |
+-------------------------------------------+------------------------------------------------------------+
| ``<<ShowIcons()>>`` | Displays all icons in /static/img/icons directory |
+-------------------------------------------+------------------------------------------------------------+
| ``<<ShowSmileys()>>`` | Displays available smileys and the corresponding markup |
Expand Down
8 changes: 8 additions & 0 deletions src/moin/help/help-en/FortuneCookies.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
= Fortune Cookies =

This item is used to show the result of the RandomQuote macro.

* I like '''MoinMoin''' Wiki
* Try out MoinMoin version 2.0, see install docs at [[https://moin-20.readthedocs.io/en/latest/admin/install.html|moin-20.readthedocs.io]]
* The '''RandomQuote''' macro uses the item '''FortuneCookies''' by default
* This is a random quote generated by the '''RandomQuote''' macro
28 changes: 28 additions & 0 deletions src/moin/help/help-en/FortuneCookies.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"action": "SAVE",
"address": "127.0.0.1",
"comment": "",
"contenttype": "text/x.moin.wiki;charset=utf-8",
"dataid": "1ae8372681474a6bafc162078dc6679d",
"externallinks": [
"https://moin-20.readthedocs.io/en/latest/admin/install.html"
],
"itemid": "237f55f536a14767b5b0f4942a8bb1d8",
"itemlinks": [],
"itemtransclusions": [],
"itemtype": "default",
"language": "en",
"mtime": 1730226097,
"name": [
"FortuneCookies"
],
"name_old": [],
"namespace": "help-en",
"rev_number": 1,
"revid": "2ee6b5b42d304ebcab3e7874df973aa7",
"sha1": "8ceccfe52b6914aeb48eef5acef9163ac074ec6c",
"size": 407,
"summary": "",
"tags": [],
"wikiname": "MyMoinMoin"
}
24 changes: 24 additions & 0 deletions src/moin/help/help-en/MoinWikiMacros.data
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,30 @@ Five random items:
<<RandomItem(5)>>


=== RandomQuote ===

This macro randomly selects a quote from a list in the specified item (default: FortuneCookies in the current namespace).

'''Markup:'''

{{{
A random Quote:

Quote 1.: <<RandomQuote()>>

Quote 2.: <<RandomQuote(help-en/FortuneCookies)>>

}}}

'''Result:'''

Two random quotes:

Quote 1.: <<RandomQuote()>>

Quote 2.: <<RandomQuote(help-en/FortuneCookies)>>


=== ShowUserGroup ===

This macro displays the contents of the metadata defined in the "usergroup" attribute.
Expand Down
10 changes: 5 additions & 5 deletions src/moin/help/help-en/MoinWikiMacros.meta
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"address": "127.0.0.1",
"comment": "",
"contenttype": "text/x.moin.wiki;charset=utf-8",
"dataid": "e5c04311b38c46029e237c0c12f3aa40",
"dataid": "3783c3fdda3b43b1a4ec0f3300c22bdb",
"externallinks": [
"https://fontawesome.com/search?o=r&m=free",
"https://moinmo.in/HelpOnMacros/Include"
Expand All @@ -19,16 +19,16 @@
],
"itemtype": "default",
"language": "en",
"mtime": 1723402687,
"mtime": 1730231040,
"name": [
"MoinWikiMacros"
],
"name_old": [],
"namespace": "help-en",
"rev_number": 1,
"revid": "dfc263543dd84e4b9fbe6b64dd983b58",
"sha1": "0064f57340dac2f337760e88e5bd57fc9ef550b1",
"size": 14479,
"revid": "931016b31ee144e7879f2ab37ebc3caa",
"sha1": "d9c425e1ccc9d1a9d862b50ea46848558d6028cf",
"size": 14886,
"summary": "",
"tags": [
"macros",
Expand Down
70 changes: 70 additions & 0 deletions src/moin/macros/RandomQuote.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copyright: 2002-2004 Juergen Hermann <[email protected]>
# Copyright: 2002 MoinMoin:ThomasWaldmann
# Copyright: 2024 MoinMoin:UlrichB
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

"""
MoinMoin - RandomQuote Macro selects a random quote from FortuneCookies or a given moinwiki item.

Usage:
<<RandomQuote()>>
<<RandomQuote(WikiTips)>>

Comments:
It will look for list delimiters on the moinwiki item in question.
It will ignore anything that is not in an "*" list.
"""

import random

from moin.constants.keys import NAME_EXACT
from moin.items import Item
from moin.i18n import _
from moin.constants.itemtypes import ITEMTYPE_NONEXISTENT
from moin.converters._util import decode_data
from moin.converters import default_registry as reg
from moin.macros._base import MacroInlineBase, fail_message, valid_item_name
from moin.utils.mime import Type, type_moin_document

from moin.utils.interwiki import get_fqname, split_fqname

random.seed()


class Macro(MacroInlineBase):
"""Return a random quote from FortuneCookies or a given wiki item"""

def macro(self, content, arguments, page_url, alternative):
item_name = arguments[0] if arguments else "FortuneCookies"
if item_name[0] in ['"', "'"] and item_name[-1] in ['"', "'"]: # remove quotes
item_name = item_name[1:-1]
if not valid_item_name(item_name):
err_msg = _("Invalid value given for item name: {0}").format(item_name)
return fail_message(err_msg, alternative)

# use same namespace as current item
namespace = split_fqname(str(page_url.path)).namespace
if not item_name.startswith(f"{namespace}/"):
item_name = get_fqname(item_name, NAME_EXACT, namespace)

# get the item with the list of quotes
item = Item.create(item_name)
if item.itemtype == ITEMTYPE_NONEXISTENT:
err_msg = _("Item does not exist or read access blocked by ACLs: {0}").format(item_name)
return fail_message(err_msg, alternative)
data = decode_data(item.content.data, item.contenttype)

# select lines looking like a list item
quotes = data.splitlines()
quotes = [quote.strip() for quote in quotes]
quotes = [quote[2:] for quote in quotes if quote.startswith("* ")]
if not quotes:
err_msg = _("No quotes found in {0}").format(item_name)
return fail_message(err_msg, alternative)

result = random.choice(quotes)
# quote may use some sort of markup, convert it to dom
input_conv = reg.get(Type(item.contenttype), type_moin_document, includes="expandall")
if not input_conv:
raise TypeError(f"We cannot handle the conversion from {item.contenttype} to the DOM tree")
return input_conv(result)
15 changes: 15 additions & 0 deletions src/moin/macros/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ def get_item_names(name="", startswith="", kind="files", skiptag="", tag=""):
return item_names


def valid_item_name(name):
"""return False if item_name not valid"""
if not isinstance(name, str):
return False
if name != name.strip():
return False
if name[0] in ["+", ".", "/"]: # allow only absolute path
return False
if name.startswith("/") or name.endswith("/"):
return False
if "//" in name: # empty ancestor name is invalid
return False
return True


def extract_h1(item_name):
"""
Return the first heading found in the item's content
Expand Down