Skip to content

Commit

Permalink
Add order_by attribute with fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilkrzyskow committed Apr 10, 2023
1 parent 4cbae0d commit 775db9d
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 6 deletions.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ This can be combined with `order` above.
sort_type: natural
```

### Order Navigation By Preference

Create a file named `.pages` in a directory and set the `order_by` attribute to `filename` or `title` to change the order of navigation items.

```yaml
order_by: title
```

This can be combined with `order` and/or `sort_type` above. If `order` is not set it will order ascending. If no preference is set, it will order by filename.

### Collapse Single Nested Pages

> **Note:** This feature is disabled by default. More on how to use it below
Expand Down Expand Up @@ -382,6 +392,7 @@ plugins:
strict: false
order: asc
sort_type: natural
order_by: title
```

### `filename`
Expand All @@ -401,9 +412,9 @@ Raise errors instead of warnings when:

Default is `true`

### `order` and `sort_type`
### `order`, `sort_type` and `order_by`

Global fallback values for the Meta attributes. Default is `None`.
Global fallback values for the Meta attributes. Default is `None` or `filename`.

<br/>

Expand Down
21 changes: 21 additions & 0 deletions mkdocs_awesome_pages_plugin/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,13 @@ class Meta:
HIDE_ATTRIBUTE = "hide"
ORDER_ATTRIBUTE = "order"
SORT_TYPE_ATTRIBUTE = "sort_type"
ORDER_BY_ATTRIBUTE = "order_by"

ORDER_ASC = "asc"
ORDER_DESC = "desc"
SORT_NATURAL = "natural"
ORDER_BY_FILENAME = "filename"
ORDER_BY_TITLE = "title"

def __init__(
self,
Expand All @@ -126,6 +129,7 @@ def __init__(
hide: bool = None,
order: Optional[str] = None,
sort_type: Optional[str] = None,
order_by: Optional[str] = None,
):
if nav is None and arrange is not None:
nav = [MetaNavItem.from_yaml(value, path) for value in arrange]
Expand All @@ -140,6 +144,7 @@ def __init__(
self.hide = hide
self.order = order
self.sort_type = sort_type
self.order_by = order_by

@staticmethod
def try_load_from(path: Optional[str]) -> "Meta":
Expand All @@ -162,6 +167,7 @@ def load_from(path: str) -> "Meta":
hide = contents.get(Meta.HIDE_ATTRIBUTE)
order = contents.get(Meta.ORDER_ATTRIBUTE)
sort_type = contents.get(Meta.SORT_TYPE_ATTRIBUTE)
order_by = contents.get(Meta.ORDER_BY_ATTRIBUTE)

if title is not None:
if not isinstance(title, str):
Expand Down Expand Up @@ -242,6 +248,20 @@ def load_from(path: str) -> "Meta":
)
)

if order_by is not None:
if order_by != Meta.ORDER_BY_TITLE and order_by != Meta.ORDER_BY_FILENAME:
raise TypeError(
'Expected "{attribute}" attribute to be one of {those} - got "{order_by}" [{context}]'.format(
attribute=Meta.ORDER_BY_ATTRIBUTE,
those=[
Meta.ORDER_BY_FILENAME,
Meta.ORDER_BY_TITLE,
],
order_by=order_by,
context=path,
)
)

return Meta(
title=title,
arrange=arrange,
Expand All @@ -252,4 +272,5 @@ def load_from(path: str) -> "Meta":
hide=hide,
order=order,
sort_type=sort_type,
order_by=order_by,
)
55 changes: 52 additions & 3 deletions mkdocs_awesome_pages_plugin/navigation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import warnings
from pathlib import Path

import mkdocs.utils
import mkdocs.utils.meta
from natsort import natsort_keygen
from typing import List, Optional, Union, Set
from typing import List, Optional, Union, Set, Dict

from mkdocs.structure.nav import (
Navigation as MkDocsNavigation,
Expand Down Expand Up @@ -79,13 +82,24 @@ def _process_children(self, children: List[NavigationItem], collapse: bool, meta
return result

def _order(self, items: List[NavigationItem], meta: Meta):
if len(items) < 2:
return

order = meta.order or self.options.order
sort_type = meta.sort_type or self.options.sort_type
if order is None and sort_type is None:
order_by = meta.order_by or self.options.order_by

if order is None and sort_type is None and order_by is None:
return
key = lambda i: basename(self._get_item_path(i))

if order_by == Meta.ORDER_BY_TITLE:
key = lambda i: get_title(i)
else:
key = lambda i: basename(self._get_item_path(i))

if sort_type == Meta.SORT_NATURAL:
key = natsort_keygen(key)

items.sort(key=key, reverse=order == Meta.ORDER_DESC)

def _nav(self, items: List[NavigationItem], meta: Meta) -> List[NavigationItem]:
Expand Down Expand Up @@ -249,3 +263,38 @@ def get_by_type(nav, T):
if item.children:
ret.extend(get_by_type(item.children, T))
return ret


# Copy of mkdocs.structure.pages.Page._set_title and Page.read_source
def get_title(item: NavigationItem) -> str:
if item.title is not None:
return item.title

if not isinstance(item, Page):
return str(item.title)

try:
with open(item.file.abs_src_path, encoding="utf-8-sig", errors="strict") as f:
source = f.read()
except OSError:
raise OSError(f"File not found: {item.file.src_path}")
except ValueError:
raise ValueError(f"Encoding error reading file: {item.file.src_path}")

page_markdown, page_meta = mkdocs.utils.meta.get_data(source)

if "title" in page_meta:
return page_meta["title"]

title = mkdocs.utils.get_markdown_title(page_markdown)

if title is None:
if item.is_homepage:
title = "Home"
else:
title = item.file.name.replace("-", " ").replace("_", " ")
# Capitalize if the filename was all lowercase, otherwise leave it as-is.
if title.lower() == title:
title = title.capitalize()

return title
10 changes: 9 additions & 1 deletion mkdocs_awesome_pages_plugin/options.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
class Options:
def __init__(
self, *, filename: str, collapse_single_pages: bool, strict: bool, order: str = None, sort_type: str = None
self,
*,
filename: str,
collapse_single_pages: bool,
strict: bool,
order: str = None,
sort_type: str = None,
order_by: str = None,
):
self.filename = filename
self.collapse_single_pages = collapse_single_pages
self.strict = strict
self.order = order
self.sort_type = sort_type
self.order_by = order_by
1 change: 1 addition & 0 deletions mkdocs_awesome_pages_plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class AwesomePagesPlugin(BasePlugin):
("strict", config_options.Type(bool, default=True)),
("order", config_options.Choice(["asc", "desc"], default=None)),
("sort_type", config_options.Choice(["natural"], default=None)),
("order_by", config_options.Choice(["filename", "title"], default=None)),
)

def __init__(self):
Expand Down

0 comments on commit 775db9d

Please sign in to comment.