diff --git a/CHANGELOG.md b/CHANGELOG.md
index 447eeae6..e3da3eb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
# Changelog
## [Unreleased]
+### Added
+- Global filters and page filters.
+
+### Fixed
+- Delete prefix in nav menu for heading mode.
## [1.0.9]
### Added
diff --git a/docs/appendix/filter.md b/docs/appendix/filter.md
deleted file mode 100644
index 0059f39a..00000000
--- a/docs/appendix/filter.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Filters and Variables
-
-## Filters
-
-* `upper`
-* `plain`
-* `all`
-* `link`
-* `apilink`
-* `sourcelink`
-* `short`: removes prefix
-
-
-## Variables
-
-* `{default}`
-* `{class}`
diff --git a/docs/examples/google_style.md b/docs/examples/google_style.md
index 205bffda..5723f394 100644
--- a/docs/examples/google_style.md
+++ b/docs/examples/google_style.md
@@ -149,3 +149,18 @@ In this example, note that:
* [Example Google Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html#example-google)
* [Example NumPy Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html#example-numpy)
+
+
+## Heading Mode
+
+The other mode to create documentation is heading. For example,
+
+~~~markdown
+## ![mkapi](google_style.ExampleClass)
+~~~
+
+create a `
` tag for the `google_style.ExampleClass`.
+
+## ![mkapi](google_style.ExampleClass)
+
+Note that an ExampleClass item in nav menu is created.
diff --git a/docs/examples/numpy_style.md b/docs/examples/numpy_style.md
index b7e4e28e..25607f53 100644
--- a/docs/examples/numpy_style.md
+++ b/docs/examples/numpy_style.md
@@ -149,3 +149,18 @@ In this example, note that:
* [Example Google Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html#example-google)
* [Example NumPy Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html#example-numpy)
+
+
+## Heading Mode
+
+The other mode to create documentation is heading. For example,
+
+~~~markdown
+## ![mkapi](numpy_style.ExampleClass)
+~~~
+
+create a `` tag for the `google_style.ExampleClass`.
+
+## ![mkapi](numpy_style.ExampleClass)
+
+Note that an ExampleClass item in nav menu is created.
diff --git a/docs/usage/filter.md b/docs/usage/filter.md
new file mode 100644
index 00000000..e561ef44
--- /dev/null
+++ b/docs/usage/filter.md
@@ -0,0 +1,99 @@
+# Filters
+
+
+
+{{ # cache:clear }}
+
+```python hide
+import sys
+
+if '../../examples' not in sys.path:
+ sys.path.insert(0, '../../examples')
+```
+
+## List of Filters
+
+### upper
+
+Use upper case letters for package and module object.
+
+~~~markdown
+### ![mkapi](filter)
+~~~
+
+### ![mkapi](filter)
+
+~~~markdown
+### ![mkapi](filter|upper)
+~~~
+
+### ![mkapi](filter|upper)
+
+### short
+
+Remove prefix.
+
+~~~markdown
+![mkapi](filter.C)
+~~~
+
+![mkapi](filter.C)
+
+~~~markdown
+![mkapi](filter.C|short)
+~~~
+
+![mkapi](filter.C|short)
+
+
+### strict
+
+Show parameters and attributes even if their description is missing.
+
+~~~markdown
+![mkapi](filter.func|strict)
+~~~
+
+![mkapi](filter.func|strict)
+
+
+## Scope of Filters
+
+### Page Scope
+
+For page scope filters, use empty object.
+
+~~~markdown
+![mkapi](|short)
+~~~
+~~~markdown
+![mkapi](filter.gen)
+~~~
+~~~markdown
+![mkapi](filter.C)
+~~~
+
+![mkapi](|short)
+![mkapi](filter.gen)
+![mkapi](filter.C)
+
+### Global Scope
+
+In `mkdocs.yaml`, select global filters:
+
+~~~yml
+# mkdocs.yml
+plugins:
+ - search
+ - mkapi:
+ src_dirs: [examples]
+ filters: [short, strict]
+~~~
diff --git a/docs/usage/module.md b/docs/usage/module.md
index 15c41a30..ddaffc3b 100644
--- a/docs/usage/module.md
+++ b/docs/usage/module.md
@@ -58,7 +58,7 @@ If you prefer upper case heading, use the `upper` filter.
## Display Members
-`all` filter generates entire module documentation including class and function members. Note that Classes and Functions sections have links to the members
+`all` filter generates entire module documentation including class and function members. Note that Classes and Functions sections have links to the members.
~~~
### ![mkapi](google_style|upper|all)
diff --git a/examples/filter.py b/examples/filter.py
new file mode 100644
index 00000000..b7d3a243
--- /dev/null
+++ b/examples/filter.py
@@ -0,0 +1,14 @@
+from typing import Iterator
+
+
+def func(x: int):
+ """Function."""
+
+
+def gen() -> Iterator[int]:
+ """Generator."""
+ yield 1
+
+
+class C:
+ """Class."""
diff --git a/mkapi/__init__.py b/mkapi/__init__.py
index 0570e5c8..eb6e77ee 100644
--- a/mkapi/__init__.py
+++ b/mkapi/__init__.py
@@ -1,4 +1,4 @@
-__version__ = "1.0.9"
+__version__ = "1.0.10"
from mkapi.core.module import get_module
from mkapi.core.node import get_node
diff --git a/mkapi/core/page.py b/mkapi/core/page.py
index 911dbeae..521fd8f2 100644
--- a/mkapi/core/page.py
+++ b/mkapi/core/page.py
@@ -1,7 +1,7 @@
"""This module provides a Page class that works with other converter."""
import re
from dataclasses import InitVar, dataclass, field
-from typing import Iterator, List, Union
+from typing import Iterator, List, Tuple, Union
from mkapi import utils
from mkapi.core import postprocess
@@ -30,8 +30,12 @@ class Page:
source: InitVar[str]
abs_src_path: str
abs_api_paths: List[str] = field(default_factory=list, repr=False)
+ filters: List[str] = field(default_factory=list, repr=False)
markdown: str = field(init=False, repr=False)
nodes: List[Union[Node, Code]] = field(default_factory=list, init=False, repr=False)
+ headings: List[Tuple[int, str]] = field(
+ default_factory=list, init=False, repr=False
+ )
def __post_init__(self, source):
self.markdown = "\n\n".join(self.split(source))
@@ -47,15 +51,21 @@ def resolve_link_from_base(self, base: Base):
def split(self, source: str) -> Iterator[str]:
cursor = 0
callback = self.resolve_link_from_base
- for index, match in enumerate(MKAPI_PATTERN.finditer(source)):
+ index = 0
+ for match in MKAPI_PATTERN.finditer(source):
start, end = match.start(), match.end()
if cursor < start:
markdown = source[cursor:start].strip()
if markdown:
yield self.resolve_link(markdown)
+ cursor = end
heading, name = match.groups()
level = len(heading)
name, filters = utils.split_filters(name)
+ if not name:
+ self.filters = filters
+ continue
+ filters = utils.update_filters(self.filters, filters)
if "code" in filters:
code = get_code(name)
self.nodes.append(code)
@@ -66,8 +76,10 @@ def split(self, source: str) -> Iterator[str]:
postprocess.transform(node, filters)
self.nodes.append(node)
markdown = node.get_markdown(level, callback=callback)
+ if level:
+ self.headings.append((level, node.object.id))
yield node_markdown(index, markdown, filters)
- cursor = end
+ index += 1
if cursor < len(source):
markdown = source[cursor:].strip()
if markdown:
diff --git a/mkapi/plugins/api.py b/mkapi/plugins/api.py
index cce442fa..a75ccc24 100644
--- a/mkapi/plugins/api.py
+++ b/mkapi/plugins/api.py
@@ -11,7 +11,7 @@
logger = logging.getLogger("mkdocs")
-def create_nav(config):
+def create_nav(config, global_filters):
nav = config["nav"]
docs_dir = config["docs_dir"]
config_dir = os.path.dirname(config["config_file_path"])
@@ -20,12 +20,14 @@ def create_nav(config):
if isinstance(page, dict):
for key, value in page.items():
if isinstance(value, str) and value.startswith("mkapi/"):
- page[key], abs_api_paths_ = collect(value, docs_dir, config_dir)
+ page[key], abs_api_paths_ = collect(
+ value, docs_dir, config_dir, global_filters
+ )
abs_api_paths.extend(abs_api_paths_)
return config, abs_api_paths
-def collect(path: str, docs_dir: str, config_dir) -> Tuple[list, list]:
+def collect(path: str, docs_dir: str, config_dir, global_filters) -> Tuple[list, list]:
_, api_path, *paths, package_path = path.split("/")
abs_api_path = os.path.join(docs_dir, api_path)
if os.path.exists(abs_api_path):
@@ -40,6 +42,7 @@ def collect(path: str, docs_dir: str, config_dir) -> Tuple[list, list]:
sys.path.insert(0, root)
package_path, filters = utils.split_filters(package_path)
+ filters = utils.update_filters(global_filters, filters)
module = get_module(package_path)
nav = []
diff --git a/mkapi/plugins/mkdocs.py b/mkapi/plugins/mkdocs.py
index 76171025..9c81a6be 100644
--- a/mkapi/plugins/mkdocs.py
+++ b/mkapi/plugins/mkdocs.py
@@ -28,6 +28,7 @@ class MkapiPlugin(BasePlugin):
config_scheme = (
("src_dirs", config_options.Type(list, default=[])),
("on_config", config_options.Type(str, default="")),
+ ("filters", config_options.Type(list, default=[])),
("callback", config_options.Type(str, default="")),
)
server = None
@@ -46,7 +47,9 @@ def on_config(self, config):
self.pages = {}
self.abs_api_paths = []
if not self.server:
- config, self.abs_api_paths = mkapi.plugins.api.create_nav(config)
+ config, self.abs_api_paths = mkapi.plugins.api.create_nav(
+ config, self.config["filters"]
+ )
global_config["config"] = config
global_config["abs_api_paths"] = self.abs_api_paths
else:
@@ -109,7 +112,9 @@ def on_page_markdown(self, markdown, page, config, files):
"""Converts Markdown source to intermidiate version."""
abs_src_path = page.file.abs_src_path
clean_page_title(page)
- page = Page(markdown, abs_src_path, self.abs_api_paths)
+ page = Page(
+ markdown, abs_src_path, self.abs_api_paths, filters=self.config["filters"]
+ )
self.pages[abs_src_path] = page
return page.markdown
@@ -125,6 +130,9 @@ def on_page_context(self, context, page, config, nav):
abs_src_path = page.file.abs_src_path
if abs_src_path in self.abs_api_paths:
clear_prefix(page.toc, 2)
+ else:
+ for level, id in self.pages[abs_src_path].headings:
+ clear_prefix(page.toc, level, id)
return context
def on_serve(self, server, config, builder):
@@ -135,9 +143,9 @@ def on_serve(self, server, config, builder):
return server
-def clear_prefix(toc, level: int):
+def clear_prefix(toc, level: int, id: str = ""):
for toc_item in toc:
- if toc_item.level >= level:
+ if toc_item.level >= level and (not id or toc_item.title == id):
toc_item.title = toc_item.title.split(".")[-1]
clear_prefix(toc_item.children, level)
return
diff --git a/mkapi/utils.py b/mkapi/utils.py
index 28f63b80..54f7577f 100644
--- a/mkapi/utils.py
+++ b/mkapi/utils.py
@@ -1,5 +1,5 @@
import importlib
-from typing import Any
+from typing import Any, List
def get_indent(line: str) -> int:
@@ -57,9 +57,35 @@ def split_filters(name):
('a.b.c', [])
>>> split_filters("a.b.c|upper|strict")
('a.b.c', ['upper', 'strict'])
+ >>> split_filters("|upper|strict")
+ ('', ['upper', 'strict'])
+ >>> split_filters("")
+ ('', [])
"""
index = name.find("|")
if index == -1:
return name, []
name, filters = name[:index], name[index + 1 :]
return name, filters.split("|")
+
+
+def update_filters(org: List[str], update: List[str]) -> List[str]:
+ """
+ Examples:
+ >>> update_filters(['upper'], ['lower'])
+ ['lower']
+ >>> update_filters(['lower'], ['upper'])
+ ['upper']
+ >>> update_filters(['long'], ['short'])
+ ['short']
+ >>> update_filters(['short'], ['long'])
+ ['long']
+ """
+ filters = org + update
+ for x, y in [["lower", "upper"], ["long", "short"]]:
+ if x in org and y in update:
+ del filters[filters.index(x)]
+ if y in org and x in update:
+ del filters[filters.index(y)]
+
+ return filters
diff --git a/mkdocs.yml b/mkdocs.yml
index 0e137b02..46995273 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -33,6 +33,7 @@ nav:
- usage/module.md
- usage/inherit.md
- usage/page.md
+ - usage/filter.md
- usage/library.py
- usage/custom.md
- Appendix:
@@ -41,7 +42,6 @@ nav:
- appendix/inherit.md
- appendix/order.md
- appendix/decorator.md
- - appendix/filter.md
- API: mkapi/api/mkapi|upper|strict
markdown_extensions: