From 143cdaa9cecbf530ebdddcd61bcb9855941f6134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torben=20B=C3=B6hnke?= <torben.boehnke-makerspace@rub.de> Date: Thu, 11 Jul 2024 12:29:26 +0200 Subject: [PATCH] add requirements.txt & customPlugins --- .../lib/mkdocs_rss_deduplicate/__init__.py | 1 + .../mkdocs_rss_deduplicate/rss_deduplicate.py | 47 +++++++ .../mkdocs_rss_deduplicate/__init__.py | 1 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 264 bytes .../rss_deduplicate.cpython-310.pyc | Bin 0 -> 1723 bytes .../mkdocs_rss_deduplicate/rss_deduplicate.py | 47 +++++++ .../rss_deduplicate.egg-info/PKG-INFO | 16 +++ .../rss_deduplicate.egg-info/SOURCES.txt | 9 ++ .../dependency_links.txt | 1 + .../rss_deduplicate.egg-info/entry_points.txt | 2 + .../rss_deduplicate.egg-info/requires.txt | 1 + .../rss_deduplicate.egg-info/top_level.txt | 1 + customPlugins/mkdocs-rss-deduplicate/setup.py | 29 +++++ .../lib/mkdocs_exclude_snippets/__init__.py | 0 .../exclude_snippets_plugin.py | 120 ++++++++++++++++++ .../mkdocs_exclude_snippets.egg-info/PKG-INFO | 3 + .../SOURCES.txt | 9 ++ .../dependency_links.txt | 1 + .../entry_points.txt | 2 + .../requires.txt | 2 + .../top_level.txt | 1 + .../mkdocs_exclude_snippets/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 206 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 182 bytes .../exclude_snippets_plugin.cpython-310.pyc | Bin 0 -> 4616 bytes .../exclude_snippets_plugin.cpython-311.pyc | Bin 0 -> 7126 bytes .../exclude_snippets_plugin.py | 120 ++++++++++++++++++ .../mkdocs_exclude_snippets/setup.py | 17 +++ requirements.txt | 50 ++++++++ 29 files changed, 480 insertions(+) create mode 100755 customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/__init__.py create mode 100755 customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/rss_deduplicate.py create mode 100755 customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__init__.py create mode 100644 customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__pycache__/__init__.cpython-310.pyc create mode 100644 customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__pycache__/rss_deduplicate.cpython-310.pyc create mode 100755 customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/rss_deduplicate.py create mode 100755 customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/PKG-INFO create mode 100755 customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/SOURCES.txt create mode 100755 customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/dependency_links.txt create mode 100755 customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/entry_points.txt create mode 100755 customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/requires.txt create mode 100755 customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/top_level.txt create mode 100755 customPlugins/mkdocs-rss-deduplicate/setup.py create mode 100755 customPlugins/mkdocs_exclude_snippets/build/lib/mkdocs_exclude_snippets/__init__.py create mode 100755 customPlugins/mkdocs_exclude_snippets/build/lib/mkdocs_exclude_snippets/exclude_snippets_plugin.py create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/PKG-INFO create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/SOURCES.txt create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/dependency_links.txt create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/entry_points.txt create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/requires.txt create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/top_level.txt create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__init__.py create mode 100644 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/__init__.cpython-310.pyc create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/__init__.cpython-311.pyc create mode 100644 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/exclude_snippets_plugin.cpython-310.pyc create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/exclude_snippets_plugin.cpython-311.pyc create mode 100755 customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/exclude_snippets_plugin.py create mode 100755 customPlugins/mkdocs_exclude_snippets/setup.py create mode 100644 requirements.txt diff --git a/customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/__init__.py b/customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/__init__.py new file mode 100755 index 000000000..5d3e80ca5 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/__init__.py @@ -0,0 +1 @@ +from .rss_deduplicate import RssDeduplicatePlugin \ No newline at end of file diff --git a/customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/rss_deduplicate.py b/customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/rss_deduplicate.py new file mode 100755 index 000000000..26377f069 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/build/lib/mkdocs_rss_deduplicate/rss_deduplicate.py @@ -0,0 +1,47 @@ +from mkdocs.plugins import BasePlugin +from mkdocs.config import config_options +from xml.etree import ElementTree as ET +import re + +class RssDeduplicatePlugin(BasePlugin): + + def on_post_build(self, config): + # Paths to your RSS feed files + rss_created_path = config['site_dir'] + '/feed_rss_created.xml' + rss_updated_path = config['site_dir'] + '/feed_rss_updated.xml' + + # Call the deduplication function on both RSS feed files + self.remove_duplicates_from_rss(rss_created_path) + self.remove_duplicates_from_rss(rss_updated_path) + self.clean_image_tags(rss_created_path) + self.clean_image_tags(rss_updated_path) + + def clean_image_tags(self, feed_path): + tree = ET.parse(feed_path) + root = tree.getroot() + + for item in root.findall('./channel/item'): + description = item.find('description').text + # Use regex to remove the width attribute snippet from the description + cleaned_description = re.sub(r'{\s*width="45%"\s*}', '', description) + # Update the description text with the cleaned version + item.find('description').text = cleaned_description + + tree.write(feed_path, encoding='utf-8', xml_declaration=True) + + def remove_duplicates_from_rss(self, feed_path): + # Parse the XML file + tree = ET.parse(feed_path) + root = tree.getroot() + + # Function to remove duplicate entries based on <title> tag + seen_titles = set() + for item in root.findall('./channel/item'): + title = item.find('title').text + if title in seen_titles: + root.find('./channel').remove(item) + else: + seen_titles.add(title) + + # Save the deduplicated XML to the same file + tree.write(feed_path, encoding='utf-8', xml_declaration=True) diff --git a/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__init__.py b/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__init__.py new file mode 100755 index 000000000..5d3e80ca5 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__init__.py @@ -0,0 +1 @@ +from .rss_deduplicate import RssDeduplicatePlugin \ No newline at end of file diff --git a/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__pycache__/__init__.cpython-310.pyc b/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d8711d70b605d63fd8e9b56e3b4b7ab636b644b GIT binary patch literal 264 zcmZ8bu?oU46inJh1hIo3;M$=EcM*rqBD!@6wFz2ml9HDUev-e`RT2CJCtp;s_~6}f z_u$@{(P&6;?zdddk*`7YCql8pg#<wmK^vlIK`9Z@j->H}qMg!ivIWSc@NH99rIVY+ zA8Nf$qhf3UxcFUc2)qy*Bfa5i*wHA-+@9s8@=9t4%$8ahHFXkD1k4n$%7ZiN6AetA lgsC9I_^cQIwfWyy#(Ax4$N8*1cY}p8!Z&gmx<lxbkQdeDOVt1X literal 0 HcmV?d00001 diff --git a/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__pycache__/rss_deduplicate.cpython-310.pyc b/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/__pycache__/rss_deduplicate.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..baee6f7007dfb93ce6fbf5dddde24fc5fe40cfdb GIT binary patch literal 1723 zcmZ`)OK&4Z5bo}I`niuJEE@!bh($6|><dU70Ik3)ZWdZ{8Z8=4rrXYhc{tteY%t@~ z?iKMDoa6qbzH-{XkP}rsPVll}q%K!~)6-R5-`C};*J~4a{(3tWmjNMv<7E4BVe%A) zLc<BCIVosFDf%pDg%df}cXGGzBH#LM9z?-UgnQh7O}H=UD<=xM`wJNaZ($cQpr-vp zqQuYnVwROK>!(#Y&1P{m*I896KswKIQHW9>OCcsHezg5Cm^_7{J_jR6L^+8Vr<}be zk;5JC!mrzek31eg;Lz+oS86QyVxDJdqBpTq-09}QqdG8tgrUY@YRc(jIOZd=VjJH9 z->J!()a(k1U_EE!(OZnx7UKjWyAu<tOpBOja=AB}3c+KkRGdlyY4G7?k#EC`IlqAi z%<M~1R2T5=P1-7+%BsK(%>6VMNf~EFG83^*W@_LXSBZRT{HC1I{jE6hJkh5OvI$|4 zH$-;eq}Lat)2a|7eKHzX=>jXSMlvaRRUBxcV1o9jP@{CAbX7FWsZsG8uTpgcagO-E zwcWt>nA<R>vo#;ie>c6VjOUfo@yQ~~d5D$og6Xm@Z98q+rhU3Re0~RW!*@P>hewbx z@nKjVUx1^@n%4A+0*h?Tu8=`z?QlTG<k!8GTf1wQ1D|K!%G3TjKn2y_m9z3||K?rn zo%d^Y7J?2y);##r${v+9x$X}~>1k4yA|C<Kh3RmiQkhvXFL(ZUp}u^XaeeyT;a6Wj zIfU8DkZW(Dr$^r$zhNd6Wm@s9oSA!|1t?IOCo;i{FlZU}?AUnoL@Hr|nb5MTv<aqJ z$&)-cE;`25;!+zXg>ls4#CR_yBrynN3r=oYR&U5Xtb@B`T)TyfdCGgRBHFPs0#R-y zZ8gytWJ4k^J1|rqOq+(Z5B&65pY5{clRMe@uQuN!$b+3MK{+_@6QrG21c-5fn1-hP zl~;Rf&(h>K#9R>h1+4HmT()%pgu#V8e*lDqwZHM%SqliWt>BihU?TAt#?zV3#j<rv zo_qlCv3v-2(3X4fBR@d%2n^H~s{bKQAEVhv%x`X|aT3nu$AE0AE<eE~pQ1Sc6Lpjj zWo*MK`5D58Xz=1~6&YoF07GE{Z5C4B>C-M0`yuVJU1vGEv(W$FASMIfgmGLZg@|L* zj^m=@iyZxK9G@?eym=#g5Y93zF@vqFY<`x1BnxkpLLr1CWMQY<lZXylQNL*d!@2F| zN@7cmdK<9mL=xL-)B<@Ap^8FCY_&~=KSB?8x+|~=zipEKp27-+|5RPlwME%w{{VEk Bz;FNn literal 0 HcmV?d00001 diff --git a/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/rss_deduplicate.py b/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/rss_deduplicate.py new file mode 100755 index 000000000..26377f069 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/mkdocs_rss_deduplicate/rss_deduplicate.py @@ -0,0 +1,47 @@ +from mkdocs.plugins import BasePlugin +from mkdocs.config import config_options +from xml.etree import ElementTree as ET +import re + +class RssDeduplicatePlugin(BasePlugin): + + def on_post_build(self, config): + # Paths to your RSS feed files + rss_created_path = config['site_dir'] + '/feed_rss_created.xml' + rss_updated_path = config['site_dir'] + '/feed_rss_updated.xml' + + # Call the deduplication function on both RSS feed files + self.remove_duplicates_from_rss(rss_created_path) + self.remove_duplicates_from_rss(rss_updated_path) + self.clean_image_tags(rss_created_path) + self.clean_image_tags(rss_updated_path) + + def clean_image_tags(self, feed_path): + tree = ET.parse(feed_path) + root = tree.getroot() + + for item in root.findall('./channel/item'): + description = item.find('description').text + # Use regex to remove the width attribute snippet from the description + cleaned_description = re.sub(r'{\s*width="45%"\s*}', '', description) + # Update the description text with the cleaned version + item.find('description').text = cleaned_description + + tree.write(feed_path, encoding='utf-8', xml_declaration=True) + + def remove_duplicates_from_rss(self, feed_path): + # Parse the XML file + tree = ET.parse(feed_path) + root = tree.getroot() + + # Function to remove duplicate entries based on <title> tag + seen_titles = set() + for item in root.findall('./channel/item'): + title = item.find('title').text + if title in seen_titles: + root.find('./channel').remove(item) + else: + seen_titles.add(title) + + # Save the deduplicated XML to the same file + tree.write(feed_path, encoding='utf-8', xml_declaration=True) diff --git a/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/PKG-INFO b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/PKG-INFO new file mode 100755 index 000000000..8e608bbb1 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/PKG-INFO @@ -0,0 +1,16 @@ +Metadata-Version: 2.1 +Name: rss-deduplicate +Version: 0.1 +Summary: An MkDocs plugin to deduplicate RSS feed items (generated by the i18n-plugin) and clean up image tags post-build. +Author: tb +Keywords: rss_deduplicate + + + This MkDocs plugin performs two key functions to enhance the quality of RSS feeds generated from MkDocs sites: + + 1. Deduplicates entries in the RSS feed that may arise due to localization (i18n) or other site generation artifacts, ensuring each item is unique. + + 2. Cleans up image tags within the RSS feed descriptions to remove any site-specific markup or styling that is not compatible with RSS feed standards or display conventions in common RSS readers. + + This ensures that the RSS feeds are clean, concise, and compliant with RSS specifications, providing a better experience for subscribers of the feed. + diff --git a/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/SOURCES.txt b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/SOURCES.txt new file mode 100755 index 000000000..eda862a77 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/SOURCES.txt @@ -0,0 +1,9 @@ +setup.py +mkdocs_rss_deduplicate/__init__.py +mkdocs_rss_deduplicate/rss_deduplicate.py +rss_deduplicate.egg-info/PKG-INFO +rss_deduplicate.egg-info/SOURCES.txt +rss_deduplicate.egg-info/dependency_links.txt +rss_deduplicate.egg-info/entry_points.txt +rss_deduplicate.egg-info/requires.txt +rss_deduplicate.egg-info/top_level.txt \ No newline at end of file diff --git a/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/dependency_links.txt b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/dependency_links.txt new file mode 100755 index 000000000..8b1378917 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/entry_points.txt b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/entry_points.txt new file mode 100755 index 000000000..5cb292d02 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/entry_points.txt @@ -0,0 +1,2 @@ +[mkdocs.plugins] +rss_deduplicate = mkdocs_rss_deduplicate.rss_deduplicate:RssDeduplicatePlugin diff --git a/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/requires.txt b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/requires.txt new file mode 100755 index 000000000..b135365ab --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/requires.txt @@ -0,0 +1 @@ +mkdocs>=1.0.4 diff --git a/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/top_level.txt b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/top_level.txt new file mode 100755 index 000000000..1651e24c4 --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/rss_deduplicate.egg-info/top_level.txt @@ -0,0 +1 @@ +mkdocs_rss_deduplicate diff --git a/customPlugins/mkdocs-rss-deduplicate/setup.py b/customPlugins/mkdocs-rss-deduplicate/setup.py new file mode 100755 index 000000000..4f9d2114a --- /dev/null +++ b/customPlugins/mkdocs-rss-deduplicate/setup.py @@ -0,0 +1,29 @@ +from setuptools import setup, find_packages + +setup( + name='rss_deduplicate', + version='0.1', + packages=find_packages(), + include_package_data=True, + install_requires=[ + 'mkdocs>=1.0.4' + ], + entry_points={ + 'mkdocs.plugins': [ + 'rss_deduplicate = mkdocs_rss_deduplicate.rss_deduplicate:RssDeduplicatePlugin', + ] + }, + author='tb', + description='An MkDocs plugin to deduplicate RSS feed items (generated by the i18n-plugin) and clean up image tags post-build.', + long_description=""" + This MkDocs plugin performs two key functions to enhance the quality of RSS feeds generated from MkDocs sites: + + 1. Deduplicates entries in the RSS feed that may arise due to localization (i18n) or other site generation artifacts, ensuring each item is unique. + + 2. Cleans up image tags within the RSS feed descriptions to remove any site-specific markup or styling that is not compatible with RSS feed standards or display conventions in common RSS readers. + + This ensures that the RSS feeds are clean, concise, and compliant with RSS specifications, providing a better experience for subscribers of the feed. + """, + + keywords='rss_deduplicate' +) \ No newline at end of file diff --git a/customPlugins/mkdocs_exclude_snippets/build/lib/mkdocs_exclude_snippets/__init__.py b/customPlugins/mkdocs_exclude_snippets/build/lib/mkdocs_exclude_snippets/__init__.py new file mode 100755 index 000000000..e69de29bb diff --git a/customPlugins/mkdocs_exclude_snippets/build/lib/mkdocs_exclude_snippets/exclude_snippets_plugin.py b/customPlugins/mkdocs_exclude_snippets/build/lib/mkdocs_exclude_snippets/exclude_snippets_plugin.py new file mode 100755 index 000000000..fe9dde61d --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/build/lib/mkdocs_exclude_snippets/exclude_snippets_plugin.py @@ -0,0 +1,120 @@ +from mkdocs.plugins import BasePlugin, event_priority +import json +import os + +class ExcludeStandaloneSnippetsPlugin(BasePlugin): + """ + A MkDocs plugin that excludes standalone snippet pages not listed in the site's navigation from the search index. + """ + + def flatten_nav(self, nav_items, parent_dir=''): + """ + Recursively flattens the navigation structure to a list of Markdown file paths. + + Args: + nav_items (list): The navigation items to process, which can be a mix of dictionaries (for nested navigation) and strings (for direct links). + parent_dir (str): The current parent directory path to prepend to nested navigation items, ensuring the full path is captured. + + Returns: + list: A list of strings, where each string is a path to a Markdown file included in the site's navigation. + """ + pages = [] + for item in nav_items: + if isinstance(item, dict): # Process nested navigation items + for nested_items in item.values(): + if isinstance(nested_items, list): + # Recurse into the list, carrying the current parent_dir + pages += self.flatten_nav(nested_items, parent_dir) + elif isinstance(nested_items, str) and nested_items.endswith('.md'): + # Add direct .md file references, prepending parent_dir if present + md_path = os.path.join(parent_dir, nested_items) + pages.append(md_path) + elif isinstance(item, str) and item.endswith('.md'): # Handle top-level .md files + md_path = os.path.join(parent_dir, item) + pages.append(md_path) + return pages + + @event_priority(-100) # Run this plugin's on_post_build event last + def on_post_build(self, config, **kwargs): + """ + The method called by MkDocs after the site has been built, to filter out standalone snippets from the search index. + + Args: + config (dict): The MkDocs config object containing site configuration details. + """ + search_index_path = os.path.join(config['site_dir'], 'search', 'search_index.json') + + with open(search_index_path, 'r') as file: + search_index = json.load(file) + + # Generate a list of normalized navigation paths for comparison + navigation_pages = [os.path.splitext(page)[0] for page in self.flatten_nav(config['nav'])] + + initial_count = len(search_index['docs']) + + filtered_docs = [] + for doc in search_index['docs']: + # Normalize the document's location for comparison, removing localization and section identifiers + parts = doc['location'].split('/') + normalized_parts = [part for part in parts if not part.startswith('#') and part != 'en'] + normalized_doc_path = '/'.join(normalized_parts).rstrip('/').replace('.md', '') + + # Include the document if its normalized path matches any navigation path + if normalized_doc_path in navigation_pages or any(normalized_doc_path.startswith(nav + '/') for nav in navigation_pages): + filtered_docs.append(doc) + # Optionally, for debugging purposes, you could uncomment the following lines to log + # documents that are identified for exclusion. This can be helpful during development + # and testing to verify that the plugin is correctly identifying documents to exclude. + # else: + # print(f"Exclude_Snippets: Excluding from search index: {doc['location']}") + + final_count = len(filtered_docs) + + # Update the search index if any documents were excluded + if initial_count != final_count: + search_index['docs'] = filtered_docs + with open(search_index_path, 'w') as file: + json.dump(search_index, file) + print("Exclude_Snippets: Successfully updated search_index.json with filtered documents.") + + # Optionally create a debug copy of the updated search index for comparison + # debug_search_index_path = os.path.join(config['site_dir'], 'search', 'search_index_debug.json') + # with open(debug_search_index_path, 'w') as debug_file: + # json.dump(search_index, debug_file) + # print("Exclude_Snippets: Created a debug copy of the updated search_index.json at 'search/search_index_debug.json'.") + + + def is_standalone_snippet(self, doc, navigation_pages): + """ + Determines if a document should be excluded from the search index. + + This method checks if the normalized path of a document is not present in the list + of navigation pages. The normalization process involves removing the '.md' extension + from the document's location for a consistent comparison with the navigation paths. + + Args: + doc (dict): A dictionary representing a document in the search index, where + 'location' is a key pointing to the document's path. + navigation_pages (list): A list of strings representing the paths of documents + included in the site's navigation, as normalized by + the flatten_nav method. + + Returns: + bool: True if the document is not found in the navigation pages and should be + excluded from the search index; False otherwise. + """ + # Normalize the document location by removing the '.md' extension. This step is crucial + # for ensuring that the document's path can be directly compared against the list of + # navigation paths, which have been similarly normalized. + normalized_doc_path = doc['location'].rstrip('.md') + + # Check if the normalized document path exists within the list of navigation pages. + # If the path is not found, the document is considered a standalone snippet that is not + # directly accessible through the site's navigation and thus should be excluded from + # the search index to avoid leading users to potentially orphaned or unintended pages. + is_excluded = normalized_doc_path not in navigation_pages + + return is_excluded + + + diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/PKG-INFO b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/PKG-INFO new file mode 100755 index 000000000..8cb8f0912 --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/PKG-INFO @@ -0,0 +1,3 @@ +Metadata-Version: 2.1 +Name: mkdocs-exclude-snippets +Version: 0.1 diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/SOURCES.txt b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/SOURCES.txt new file mode 100755 index 000000000..d157cd5d9 --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/SOURCES.txt @@ -0,0 +1,9 @@ +setup.py +mkdocs_exclude_snippets/__init__.py +mkdocs_exclude_snippets/exclude_snippets_plugin.py +mkdocs_exclude_snippets.egg-info/PKG-INFO +mkdocs_exclude_snippets.egg-info/SOURCES.txt +mkdocs_exclude_snippets.egg-info/dependency_links.txt +mkdocs_exclude_snippets.egg-info/entry_points.txt +mkdocs_exclude_snippets.egg-info/requires.txt +mkdocs_exclude_snippets.egg-info/top_level.txt \ No newline at end of file diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/dependency_links.txt b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/dependency_links.txt new file mode 100755 index 000000000..8b1378917 --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/entry_points.txt b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/entry_points.txt new file mode 100755 index 000000000..e458d2f7a --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/entry_points.txt @@ -0,0 +1,2 @@ +[mkdocs.plugins] +exclude_snippets = mkdocs_exclude_snippets.exclude_snippets_plugin:ExcludeStandaloneSnippetsPlugin diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/requires.txt b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/requires.txt new file mode 100755 index 000000000..d912869d8 --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/requires.txt @@ -0,0 +1,2 @@ +mkdocs +pyyaml diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/top_level.txt b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/top_level.txt new file mode 100755 index 000000000..12de9a895 --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets.egg-info/top_level.txt @@ -0,0 +1 @@ +mkdocs_exclude_snippets diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__init__.py b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__init__.py new file mode 100755 index 000000000..e69de29bb diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/__init__.cpython-310.pyc b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7a728b0594613b716c96437833f1da151edb280 GIT binary patch literal 206 zcmd1j<>g`k0`dMksUZ3>h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o5j-KO;XkRlg)j z-z7h}G&eP`q*%WwF)t-QSD_@e7{~#Uy1B*r$)&|5`MCi(rRkY@#rnC~Df!98@u?Nb wIi)G7@x^(W1qG=<)wsmt<1_OzOXB183My}L*yQG?l;)(`ft*sz1SD7(09@iZi2wiq literal 0 HcmV?d00001 diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/__init__.cpython-311.pyc b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/__init__.cpython-311.pyc new file mode 100755 index 0000000000000000000000000000000000000000..6f663430ae53d28aa1b27bc1dce79669837fa27c GIT binary patch literal 182 zcmZ3^%ge<81mgX7QbF`%5CH>>P{wCAAY(d13PUi1CZpd<h9V{)|1(JPmuHGqOm1R! zYEf}PVsdIsZgxt3a&dfWMRHDQN@{#@US>f-YDqCp@%Z@6yv&mLc)fzkUmP~M`6;D2 dsdh!IK$Ags7xM#&56p~=j2{?aL=iJk3;@%=FQotg literal 0 HcmV?d00001 diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/exclude_snippets_plugin.cpython-310.pyc b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/exclude_snippets_plugin.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..309803a909356ed964b2e67f49cc9aaa9b9e2a86 GIT binary patch literal 4616 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 literal 0 HcmV?d00001 diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/exclude_snippets_plugin.cpython-311.pyc b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/__pycache__/exclude_snippets_plugin.cpython-311.pyc new file mode 100755 index 0000000000000000000000000000000000000000..50a5190a4802b7ad596c5c0a0a7d4cc33388af2d GIT binary patch literal 7126 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 U6fn7Yp1u6gX!&M~c7vV&08N)I&;S4c literal 0 HcmV?d00001 diff --git a/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/exclude_snippets_plugin.py b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/exclude_snippets_plugin.py new file mode 100755 index 000000000..fe9dde61d --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/mkdocs_exclude_snippets/exclude_snippets_plugin.py @@ -0,0 +1,120 @@ +from mkdocs.plugins import BasePlugin, event_priority +import json +import os + +class ExcludeStandaloneSnippetsPlugin(BasePlugin): + """ + A MkDocs plugin that excludes standalone snippet pages not listed in the site's navigation from the search index. + """ + + def flatten_nav(self, nav_items, parent_dir=''): + """ + Recursively flattens the navigation structure to a list of Markdown file paths. + + Args: + nav_items (list): The navigation items to process, which can be a mix of dictionaries (for nested navigation) and strings (for direct links). + parent_dir (str): The current parent directory path to prepend to nested navigation items, ensuring the full path is captured. + + Returns: + list: A list of strings, where each string is a path to a Markdown file included in the site's navigation. + """ + pages = [] + for item in nav_items: + if isinstance(item, dict): # Process nested navigation items + for nested_items in item.values(): + if isinstance(nested_items, list): + # Recurse into the list, carrying the current parent_dir + pages += self.flatten_nav(nested_items, parent_dir) + elif isinstance(nested_items, str) and nested_items.endswith('.md'): + # Add direct .md file references, prepending parent_dir if present + md_path = os.path.join(parent_dir, nested_items) + pages.append(md_path) + elif isinstance(item, str) and item.endswith('.md'): # Handle top-level .md files + md_path = os.path.join(parent_dir, item) + pages.append(md_path) + return pages + + @event_priority(-100) # Run this plugin's on_post_build event last + def on_post_build(self, config, **kwargs): + """ + The method called by MkDocs after the site has been built, to filter out standalone snippets from the search index. + + Args: + config (dict): The MkDocs config object containing site configuration details. + """ + search_index_path = os.path.join(config['site_dir'], 'search', 'search_index.json') + + with open(search_index_path, 'r') as file: + search_index = json.load(file) + + # Generate a list of normalized navigation paths for comparison + navigation_pages = [os.path.splitext(page)[0] for page in self.flatten_nav(config['nav'])] + + initial_count = len(search_index['docs']) + + filtered_docs = [] + for doc in search_index['docs']: + # Normalize the document's location for comparison, removing localization and section identifiers + parts = doc['location'].split('/') + normalized_parts = [part for part in parts if not part.startswith('#') and part != 'en'] + normalized_doc_path = '/'.join(normalized_parts).rstrip('/').replace('.md', '') + + # Include the document if its normalized path matches any navigation path + if normalized_doc_path in navigation_pages or any(normalized_doc_path.startswith(nav + '/') for nav in navigation_pages): + filtered_docs.append(doc) + # Optionally, for debugging purposes, you could uncomment the following lines to log + # documents that are identified for exclusion. This can be helpful during development + # and testing to verify that the plugin is correctly identifying documents to exclude. + # else: + # print(f"Exclude_Snippets: Excluding from search index: {doc['location']}") + + final_count = len(filtered_docs) + + # Update the search index if any documents were excluded + if initial_count != final_count: + search_index['docs'] = filtered_docs + with open(search_index_path, 'w') as file: + json.dump(search_index, file) + print("Exclude_Snippets: Successfully updated search_index.json with filtered documents.") + + # Optionally create a debug copy of the updated search index for comparison + # debug_search_index_path = os.path.join(config['site_dir'], 'search', 'search_index_debug.json') + # with open(debug_search_index_path, 'w') as debug_file: + # json.dump(search_index, debug_file) + # print("Exclude_Snippets: Created a debug copy of the updated search_index.json at 'search/search_index_debug.json'.") + + + def is_standalone_snippet(self, doc, navigation_pages): + """ + Determines if a document should be excluded from the search index. + + This method checks if the normalized path of a document is not present in the list + of navigation pages. The normalization process involves removing the '.md' extension + from the document's location for a consistent comparison with the navigation paths. + + Args: + doc (dict): A dictionary representing a document in the search index, where + 'location' is a key pointing to the document's path. + navigation_pages (list): A list of strings representing the paths of documents + included in the site's navigation, as normalized by + the flatten_nav method. + + Returns: + bool: True if the document is not found in the navigation pages and should be + excluded from the search index; False otherwise. + """ + # Normalize the document location by removing the '.md' extension. This step is crucial + # for ensuring that the document's path can be directly compared against the list of + # navigation paths, which have been similarly normalized. + normalized_doc_path = doc['location'].rstrip('.md') + + # Check if the normalized document path exists within the list of navigation pages. + # If the path is not found, the document is considered a standalone snippet that is not + # directly accessible through the site's navigation and thus should be excluded from + # the search index to avoid leading users to potentially orphaned or unintended pages. + is_excluded = normalized_doc_path not in navigation_pages + + return is_excluded + + + diff --git a/customPlugins/mkdocs_exclude_snippets/setup.py b/customPlugins/mkdocs_exclude_snippets/setup.py new file mode 100755 index 000000000..8d34d2fc3 --- /dev/null +++ b/customPlugins/mkdocs_exclude_snippets/setup.py @@ -0,0 +1,17 @@ +from setuptools import setup, find_packages + +setup( + name='mkdocs-exclude-snippets', + version='0.1', + packages=find_packages(), + include_package_data=True, + install_requires=[ + 'mkdocs', + 'pyyaml', # Ensure you include all necessary dependencies + ], + entry_points={ + 'mkdocs.plugins': [ + 'exclude_snippets = mkdocs_exclude_snippets.exclude_snippets_plugin:ExcludeStandaloneSnippetsPlugin', + ] + } +) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..e1692cfe5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,50 @@ +Babel==2.13.1 +bracex==2.4 +certifi==2023.7.22 +charset-normalizer==3.3.2 +click==8.1.7 +colorama==0.4.6 +ghp-import==2.1.0 +gitdb==4.0.11 +GitPython==3.1.40 +idna==3.4 +Jinja2==3.1.2 +lxml==4.9.3 +Markdown==3.5.1 +MarkupSafe==2.1.3 +mergedeep==1.3.4 +mkdocs==1.5.3 +mkdocs-footermatter==1.3.2 +mkdocs-git-revision-date-localized-plugin==1.2.1 +mkdocs-glightbox==0.3.4 +mkdocs-material==9.4.7 +mkdocs-material-extensions==1.3 +mkdocs-rss-plugin==1.8.0 +mkdocs-static-i18n==1.2.0 +mkdocs-table-reader-plugin==2.0.3 +mkdocs-video==1.5.0 +numpy==1.26.1 +packaging==23.2 +paginate==0.5.6 +pandas==2.1.2 +pathspec==0.11.2 +pendulum==2.1.2 +platformdirs==3.11.0 +Pygments==2.16.1 +pymdown-extensions==10.3.1 +python-dateutil==2.8.2 +pytz==2023.3.post1 +pytzdata==2020.1 +PyYAML==6.0.1 +pyyaml_env_tag==0.1 +regex==2023.10.3 +requests==2.31.0 +six==1.16.0 +smmap==5.0.1 +tabulate==0.9.0 +tzdata==2023.3 +urllib3==2.0.7 +watchdog==3.0.0 +wcmatch==8.5.2 +-e ./customPlugins/mkdocs_exclude_snippets +-e ./customPlugins/mkdocs-rss-deduplicate -- GitLab