diff --git a/mkdocs_awesome_pages_plugin/meta.py b/mkdocs_awesome_pages_plugin/meta.py index 788fe6b..add9f8a 100644 --- a/mkdocs_awesome_pages_plugin/meta.py +++ b/mkdocs_awesome_pages_plugin/meta.py @@ -108,6 +108,7 @@ class Meta: COLLAPSE_ATTRIBUTE = "collapse" COLLAPSE_SINGLE_PAGES_ATTRIBUTE = "collapse_single_pages" HIDE_ATTRIBUTE = "hide" + IGNORE_CASE_ATTRIBUTE = "ignore_case" ORDER_ATTRIBUTE = "order" SORT_TYPE_ATTRIBUTE = "sort_type" ORDER_BY_ATTRIBUTE = "order_by" @@ -128,6 +129,7 @@ def __init__( collapse: bool = None, collapse_single_pages: bool = None, hide: bool = None, + ignore_case: bool = None, order: Optional[str] = None, sort_type: Optional[str] = None, order_by: Optional[str] = None, @@ -143,6 +145,7 @@ def __init__( self.collapse = collapse self.collapse_single_pages = collapse_single_pages self.hide = hide + self.ignore_case = ignore_case self.order = order self.sort_type = sort_type self.order_by = order_by @@ -173,6 +176,7 @@ def load_from(path: str) -> "Meta": collapse = contents.get(Meta.COLLAPSE_ATTRIBUTE) collapse_single_pages = contents.get(Meta.COLLAPSE_SINGLE_PAGES_ATTRIBUTE) hide = contents.get(Meta.HIDE_ATTRIBUTE) + ignore_case = contents.get(Meta.IGNORE_CASE_ATTRIBUTE) order = contents.get(Meta.ORDER_ATTRIBUTE) sort_type = contents.get(Meta.SORT_TYPE_ATTRIBUTE) order_by = contents.get(Meta.ORDER_BY_ATTRIBUTE) @@ -241,6 +245,15 @@ def load_from(path: str) -> "Meta": context=path, ) ) + if ignore_case is not None: + if not isinstance(ignore_case, bool): + raise TypeError( + 'Expected "{attribute}" attribute to be a boolean - got {type} [{context}]'.format( + attribute=Meta.IGNORE_CASE_ATTRIBUTE, + type=type(ignore_case), + context=path, + ) + ) if order is not None: if order != Meta.ORDER_ASC and order != Meta.ORDER_DESC: raise TypeError( @@ -278,6 +291,7 @@ def load_from(path: str) -> "Meta": collapse=collapse, collapse_single_pages=collapse_single_pages, hide=hide, + ignore_case=ignore_case, order=order, sort_type=sort_type, order_by=order_by, diff --git a/mkdocs_awesome_pages_plugin/navigation.py b/mkdocs_awesome_pages_plugin/navigation.py index 21f24b0..7e5717f 100644 --- a/mkdocs_awesome_pages_plugin/navigation.py +++ b/mkdocs_awesome_pages_plugin/navigation.py @@ -12,7 +12,7 @@ _add_previous_and_next_links, ) from mkdocs.structure.pages import Page -from natsort import natsort_keygen +from natsort import natsort_keygen, ns from .meta import Meta, MetaNavItem, MetaNavRestItem, RestItemList from .options import Options @@ -95,13 +95,19 @@ def _order(self, items: List[NavigationItem], meta: Meta): if order is None and sort_type is None and order_by is None: return + ignore_case = meta.ignore_case or self.options.ignore_case + if order_by == Meta.ORDER_BY_TITLE: - key = lambda i: self._get_item_title(i) + item_key = lambda i: self._get_item_title(i) else: - key = lambda i: basename(self._get_item_path(i)) + item_key = lambda i: basename(self._get_item_path(i)) if sort_type == Meta.SORT_NATURAL: - key = natsort_keygen(key) + key = natsort_keygen(item_key, alg=ns.IGNORECASE if ignore_case else ns.DEFAULT) + elif ignore_case: + key = lambda i: item_key(i).casefold() + else: + key = item_key items.sort(key=key, reverse=order == Meta.ORDER_DESC) diff --git a/mkdocs_awesome_pages_plugin/options.py b/mkdocs_awesome_pages_plugin/options.py index bb8e6c3..66f4431 100644 --- a/mkdocs_awesome_pages_plugin/options.py +++ b/mkdocs_awesome_pages_plugin/options.py @@ -8,6 +8,7 @@ def __init__( order: str = None, sort_type: str = None, order_by: str = None, + ignore_case: bool = None, ): self.filename = filename self.collapse_single_pages = collapse_single_pages @@ -15,3 +16,4 @@ def __init__( self.order = order self.sort_type = sort_type self.order_by = order_by + self.ignore_case = ignore_case diff --git a/mkdocs_awesome_pages_plugin/tests/navigation/test_order_and_sort.py b/mkdocs_awesome_pages_plugin/tests/navigation/test_order_and_sort.py index 860d7c8..a3ecc19 100644 --- a/mkdocs_awesome_pages_plugin/tests/navigation/test_order_and_sort.py +++ b/mkdocs_awesome_pages_plugin/tests/navigation/test_order_and_sort.py @@ -289,3 +289,91 @@ def test_nav_rest_desc_natural(self): [self.page("30"), self.page("1000"), self.page("200"), self.page("4")], ) self.assertValidNavigation(navigation.to_mkdocs()) + + def test_section_asc_ignore_case(self): + navigation = self.createAwesomeNavigation( + [ + self.page("B"), + self.page("a"), + self.page("C"), + Meta(ignore_case=True, order=Meta.ORDER_ASC), + ] + ) + + self.assertNavigationEqual( + navigation.items, + [ + self.page("a"), + self.page("B"), + self.page("C"), + ], + ) + self.assertValidNavigation(navigation.to_mkdocs()) + + def test_section_asc_natural_ignore_case(self): + navigation = self.createAwesomeNavigation( + [ + self.page("B"), + self.page("a"), + self.page("C"), + Meta( + ignore_case=True, + order=Meta.ORDER_ASC, + sort_type=Meta.SORT_NATURAL, + ), + ] + ) + + self.assertNavigationEqual( + navigation.items, + [ + self.page("a"), + self.page("B"), + self.page("C"), + ], + ) + self.assertValidNavigation(navigation.to_mkdocs()) + + def test_section_desc_ignore_case(self): + navigation = self.createAwesomeNavigation( + [ + self.page("B"), + self.page("a"), + self.page("C"), + Meta(ignore_case=True, order=Meta.ORDER_DESC), + ] + ) + + self.assertNavigationEqual( + navigation.items, + [ + self.page("C"), + self.page("B"), + self.page("a"), + ], + ) + self.assertValidNavigation(navigation.to_mkdocs()) + + def test_section_desc_natural_ignore_case(self): + navigation = self.createAwesomeNavigation( + [ + self.page("B"), + self.page("a"), + self.page("C"), + Meta( + ignore_case=True, + order=Meta.ORDER_DESC, + sort_type=Meta.SORT_NATURAL, + ), + ] + ) + + self.assertNavigationEqual( + navigation.items, + [ + self.page("C"), + self.page("B"), + self.page("a"), + ], + ) + self.assertValidNavigation(navigation.to_mkdocs())