diff --git a/doc/Makefile b/doc/Makefile index dd2769a1dd6..8a5b6e3de1c 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -5,8 +5,6 @@ include $(MODULE_TOPDIR)/include/Make/Other.make FILES := $(wildcard *.html) # So far, we disntinguished user and contributor documentation here by # extension. This is no longer possible with Markdown. -# These are currently maunally added to mam/mkdocs/scripts/hook_list_scripts.py -# to generate the correct links to edit on GitHub. MDFILES := grass_database.md projectionintro.md default: $(patsubst %,$(HTMLDIR)/%,$(FILES)) $(patsubst %,$(MDDIR)/source/%,$(MDFILES)) diff --git a/man/mkdocs/overrides/partials/actions.html b/man/mkdocs/overrides/partials/actions.html index cba857c0d32..0c89301ab52 100644 --- a/man/mkdocs/overrides/partials/actions.html +++ b/man/mkdocs/overrides/partials/actions.html @@ -1,14 +1,9 @@ {% if page.edit_url %} {% set toolname = page.file.src_path.split("/")[-1] | replace(".md", "") %} - {# Default to the normal edit URL #} - {% set custom_edit_url = page.edit_url %} - {% set ghpath = github_path(toolname, config.extra.scripts_tools) %} - + {% set ghpath = github_path(toolname, config.extra.source_docs) %} {% if ghpath %} - {% set custom_edit_url = page.edit_url ~ ghpath %} {% set custom_edit_url = page.edit_url | replace(toolname, ghpath ~ "/" ~ toolname) %} {% if "content.action.edit" in features %} diff --git a/man/mkdocs/scripts/hook_list_scripts.py b/man/mkdocs/scripts/hook_list_scripts.py index ce65722d9b0..1cb75eb4d9e 100644 --- a/man/mkdocs/scripts/hook_list_scripts.py +++ b/man/mkdocs/scripts/hook_list_scripts.py @@ -3,92 +3,13 @@ from jinja2 import Environment -def github_path(toolname, scripts_tools): - """Finds GitHub path for a tool in GRASS GIS with subtool handling""" - - auto_generated_indexes = [ - "database", - "db", - "display", - "general", - "imagery", - "miscellaneous", - "postscript", - "raster", - "raster3d", - "temporal", - "vector", - ] - - # Special cases for documentation pages that don't match the pattern matching scheme - special_docs = [ - {"name": "projectionintro", "path": "doc"}, - {"name": "grass_database", "path": "doc"}, - {"name": "databaseintro", "path": "db"}, - ] - - # Exit early if toolname is empty - if not toolname: +def github_path(toolname: str, source_docs: dict[str, str]): + """Return the GitHub path for the given toolname""" + try: + return source_docs[toolname] + except KeyError: return None - # Handle special cases - if toolname in [x["name"] for x in special_docs]: - return next((x["path"] for x in special_docs if x["name"] == toolname), None) - - # Convert filter() results to a list - tool_matches = list(filter(lambda x: toolname in x, scripts_tools)) - - # print(f"Tool Matches: {tool_matches}") - - # If there's exactly one match, return it immediately - if len(tool_matches) == 1: - return tool_matches[0] - - # Prioritize exact matches - exact_match = next((x for x in tool_matches if x.endswith(toolname)), None) - # print(f"Exact - Tool Matches: {exact_match}") - if toolname in auto_generated_indexes: - # print(f"Exact Match - Autogenerated: {exact_match}") - return None - if exact_match: - return exact_match - - # Prefer major categories (raster, vector, imagery, temporal, etc.) - category_match = next( - (x for x in tool_matches if not x.startswith("scripts/")), None - ) - # print(f"Category - Tool Matches: {category_match}") - if category_match: - return category_match - - # Check for subtools in the same directory (e.g., r.sim -> r.sim.water, r.sim.sediment) - subtool_prefix = toolname + "." # Ensure it matches the full prefix - sub_tool_matches = [x for x in tool_matches if x.startswith(subtool_prefix)] - - # print(f"Subtool - Tool Matches: {sub_tool_matches}") - # If exactly one subtool match exists, return it - if len(sub_tool_matches) == 1: - return sub_tool_matches[0] - - # If multiple subtools exist, prioritize based on name length (more specific subtools come first) - if sub_tool_matches: - sub_tool_matches.sort(key=len) # Shorter names first - return sub_tool_matches[0] # Return the most specific match - - # Handle special case for "intro" pages - # print(f"Intro Doc - Matches: {tool_matches}") - if toolname.endswith("intro"): - return toolname.replace("intro", "") - - # Special case for gui/wxpython/docs - if toolname.startswith("g."): - # print(f"GUI Docs: {toolname}") - tool_dir = toolname.split(".")[-1] - return f"gui/wxpython/{tool_dir}/{toolname}" - - # If nothing else, return the first available match - return tool_matches[0] if tool_matches else None - def on_env(env: Environment, config, files): """Enable loopcontrols extension in Jinja2""" @@ -103,20 +24,32 @@ def on_config(config): store it in MkDocs extra config. These are used to generate the correct links to the documentation in GitHub. """ - scripts_dir = Path("source") - scripts_tools = [] - url_pattern = re.compile( - r"https://github.com/OSGeo/grass/tree/main/([^ )]+)" - ) # Read the mkdocs.yml file + source_dir = Path("source") + + # Dict to store the documentation path for each tool in GitHub + # the key is the doc name and the value is the path in the GitHub repository + source_docs = {} - for file in scripts_dir.glob("*.md"): + # Read the source files and extract the GitHub path from the Available at link at the bottom of the page + pattern = re.compile( + r"Available at:\s*\[(?P.*?)\]\(https://github\.com/OSGeo/grass/tree/main/(?P.*?)\)" + ) + + for file in source_dir.glob("*.md"): with file.open() as f: for line in f: - match = url_pattern.search(line) + match = pattern.search(line) if match: - toolname = match.group(1).strip() - scripts_tools.append(toolname) + # Extract the entire link text and the GitHub path. + text = match.group("text") + gh_path = match.group("gh_path").strip() + + # Remove the trailing "source code" from the text to get the tool name. + toolname = re.sub( + r"\s*source\s+code\s*$", "", text, flags=re.IGNORECASE + ).strip() + source_docs[toolname] = gh_path # Store in MkDocs extra config - config["extra"]["scripts_tools"] = scripts_tools + config["extra"]["source_docs"] = source_docs return config