Skip to content

Commit

Permalink
Move deduplicate_toc to a separate Markdown extension
Browse files Browse the repository at this point in the history
  • Loading branch information
oprypin committed Jan 1, 2021
1 parent 7e7264d commit d575e47
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 52 deletions.
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,13 @@ plugins:
- mkdocstrings:
default_handler: crystal
watch: [src]
```
<details><summary>Recommended Markdown extensions</summary>

```yaml
markdown_extensions:
- pymdownx.highlight
- pymdownx.magiclink
- pymdownx.saneheaders
- pymdownx.superfences
- deduplicate-toc
```
</details>
Expand Down Expand Up @@ -135,10 +132,6 @@ A list of command line arguments to pass to `crystal doc`. Mainly used to choose

Each inserted identifier gets an HTML heading. The default heading is `<h2>`, and sub-headings in it are shifted accordingly (so if you write headings in doc comments, you're welcome to start with `#` `<h1>`). You can change this heading level, either the default one or per-identifier.

* `deduplicate_toc:`: (**`true`**/`false`)

Set to `false` to skip the feature that de-duplicates consecutive items in the table of contents. This feature is needed because Crystal can have multiple overloads of a method but in the ToC only their names are shown.

### Example of a global config

```yaml
Expand Down Expand Up @@ -166,3 +159,9 @@ plugins:
rendering:
heading_level: 3
```

### Extras

#### "deduplicate-toc" extension

For most [usages it is recommended](#usage) to enable the "deduplicate-toc" Markdown extension, which comes bundled with mkdocstrings-crystal. It de-duplicates consecutive items that have the same title in the table of contents. This is useful because Crystal can have multiple overloads of a method but in the ToC only their names are shown.
37 changes: 37 additions & 0 deletions mkdocstrings/handlers/crystal/deduplicate_toc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import xml.etree.ElementTree as etree
from typing import List

from markdown import Markdown # type: ignore
from markdown.extensions import Extension, fenced_code # type: ignore
from markdown.treeprocessors import Treeprocessor


def _deduplicate_toc(toc: List[dict]) -> None:
i = 0
while i < len(toc):
el = toc[i]
if el.get("children"):
_deduplicate_toc(el["children"])
elif i > 0 and el["name"] == toc[i - 1]["name"]:
del toc[i]
continue
i += 1


class _TocDeduplicatingTreeprocessor(Treeprocessor):
def run(self, root: etree.Element):
try:
toc = self.md.toc_tokens
except AttributeError:
return
_deduplicate_toc(toc)


class DeduplicateTocExtension(Extension):
def extendMarkdown(self, md: Markdown) -> None:
md.treeprocessors.register(
_TocDeduplicatingTreeprocessor(md), "mkdocstrings_crystal_deduplicate_toc", 4
)


makeExtension = DeduplicateTocExtension
43 changes: 1 addition & 42 deletions mkdocstrings/handlers/crystal/renderer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import collections
import contextlib
import xml.etree.ElementTree as etree
from typing import List, Optional, TypeVar, Union
from typing import Optional, TypeVar, Union

import jinja2
from markdown import Markdown # type: ignore
Expand All @@ -23,7 +23,6 @@ class CrystalRenderer(base.BaseRenderer):
default_config: dict = {
"show_source_links": True,
"heading_level": 2,
"deduplicate_toc": True,
}

def render(self, data: DocItem, config: dict) -> str:
Expand All @@ -39,17 +38,6 @@ def render(self, data: DocItem, config: dict) -> str:
)

def update_env(self, md: Markdown, config: dict) -> None:
subconfig = collections.ChainMap(self.default_config)
try:
subconfig = subconfig.new_child(
config["mkdocstrings"]["handlers"]["crystal"]["rendering"]
)
except KeyError:
pass

if subconfig["deduplicate_toc"]:
DeduplicateTocExtension().extendMarkdown(md)

extensions = list(config["mdx"])
extensions.append(_EscapeHtmlExtension())
extensions.append(XrefExtension(self.collector))
Expand Down Expand Up @@ -159,32 +147,3 @@ def run(self, root: etree.Element):
# Put the `code` into the `span`, with a special attribute for mkdocstrings to pick up.
span.append(el)
span.set("data-mkdocstrings-identifier", ref_obj.abs_id)


def _deduplicate_toc(toc: List[dict]) -> None:
i = 0
while i < len(toc):
el = toc[i]
if el.get("children"):
_deduplicate_toc(el["children"])
elif i > 0 and el["name"] == toc[i - 1]["name"]:
del toc[i]
continue
i += 1


class _TocDeduplicatingTreeprocessor(Treeprocessor):
def run(self, root: etree.Element):
try:
toc = self.md.toc_tokens
except AttributeError:
return
_deduplicate_toc(toc)


class DeduplicateTocExtension(Extension):
def extendMarkdown(self, md: Markdown) -> None:
md.registerExtension(self)
md.treeprocessors.register(
_TocDeduplicatingTreeprocessor(md), "mkdocstrings_crystal_deduplicate_toc", 4
)
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ packages = [
{ include = "mkdocstrings" }
]

[tool.poetry.plugins."markdown.extensions"]
deduplicate-toc = "mkdocstrings.handlers.crystal.deduplicate_toc:DeduplicateTocExtension"

[tool.poetry.dependencies]
python = "^3.7"
mkdocstrings = { git = "https:/pawamoy/mkdocstrings.git", branch = "master" }
Expand Down
4 changes: 2 additions & 2 deletions tests/test_renderer.py → tests/test_deduplicate_toc.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import pytest

from mkdocstrings.handlers.crystal import renderer
from mkdocstrings.handlers.crystal import deduplicate_toc


@pytest.mark.golden_test("deduplicate_toc/**/*.yml")
def test_deduplicate_toc(golden):
toc = list(golden["input"])
renderer._deduplicate_toc(toc)
deduplicate_toc._deduplicate_toc(toc)
assert toc == golden.out.get("output")

0 comments on commit d575e47

Please sign in to comment.