Skip to content

Commit

Permalink
feat: support real world use cases (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
KyleKing authored Jan 12, 2023
1 parent c150553 commit 15a3ec6
Show file tree
Hide file tree
Showing 10 changed files with 361 additions and 141 deletions.
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ repos:
- id: pretty-format-json
args: [--autofix, --indent=4]
- id: trailing-whitespace
exclude: tests/fixtures\.md
exclude: tests/fixtures.*\.md
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0
hooks:
Expand Down Expand Up @@ -56,6 +56,7 @@ repos:
- mdformat-beautysh
- mdformat-black
- mdformat-config
- mdformat-footnote
- mdformat-frontmatter
- mdformat-gfm
- mdformat-tables
Expand Down
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python 3.10.5 3.8.4 3.9.4 3.7.12
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ Add this package wherever you use `mdformat` and the plugin will be auto-recogni

Tip: this package has a pip extra, `recommended`, of plugins that work well with mkdocs:

- mdformat-admon
- mdformat-beautysh
- mdformat-black
- mdformat-config
- mdformat-frontmatter
- mdformat-gfm
- mdformat-tables
- mdformat-toc
- mdformat-web
- [mdformat-admon](https://pypi.org/project/mdformat-admon)
- [mdformat-beautysh](https://pypi.org/project/mdformat-beautysh)
- [mdformat-black](https://pypi.org/project/mdformat-black)
- [mdformat-config](https://pypi.org/project/mdformat-config)
- [mdformat-footnote](https://pypi.org/project/mdformat-footnote)
- [mdformat-frontmatter](https://pypi.org/project/mdformat-frontmatter)
- [mdformat-simple-breaks](https://pypi.org/project/mdformat-simple-breaks)
- [mdformat-tables](https://pypi.org/project/mdformat-tables)
- [mdformat-toc](https://pypi.org/project/mdformat-toc)
- [mdformat-web](https://pypi.org/project/mdformat-web)

### Pre-commit

Expand All @@ -49,7 +50,7 @@ repos:
pipx install mdformat
pipx inject mdformat mdformat-mkdocs
# Or
# pipx inject mdformat-gfm "mdformat-mkdocs[recommended]"
# pipx inject mdformat "mdformat-mkdocs[recommended]"
```

## Caveats
Expand Down
2 changes: 1 addition & 1 deletion mdformat_mkdocs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

__version__ = "0.0.1"

from .plugin import RENDERERS, update_mdit # noqa: F401
from .plugin import POSTPROCESSORS, RENDERERS, update_mdit # noqa: F401
78 changes: 58 additions & 20 deletions mdformat_mkdocs/plugin.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,70 @@
from functools import partial
from typing import Mapping
import re
from typing import Dict, Mapping

from markdown_it import MarkdownIt
from mdformat.renderer import RenderContext, RenderTreeNode
from mdformat.renderer.typing import Render

_MKDOCS_INDENT_COUNT = 4
"""Use 4-spaces for mkdocs."""


def update_mdit(mdit: MarkdownIt) -> None:
"""No changes to markdown parsing are necessary."""
"""Ensure that 4-spaces are converted to HTML correctly."""
...


def _render_list(node: RenderTreeNode, context: RenderContext, bullet: str) -> str:
"""Render a `RenderTreeNode` consistent with `mkdocs`."""
_RE_INDENT = re.compile(r"(?P<indent>\s*)(?P<content>.*)")
"""Match `indent` and `content` against line`."""

_RE_LIST_ITEM = re.compile(r"(?P<bullet>[\-\*\d\.]+)\s+(?P<item>.+)")
"""Match `bullet` and `item` against `content`."""


def _normalize_list(text: str, node: RenderTreeNode, context: RenderContext) -> str:
"""No changes to markdown parsing are necessary."""
eol = "\n" # PLANNED: What about carriage returns?
indent = " " * _MKDOCS_INDENT_COUNT

rendered = ""
indent = " " * 4
with context.indented(len(indent)): # Modifies context.env['indent_width']
inner_indent = indent * (context.env["indent_width"] // len(indent) - 1)
for child in node.children:
content = child.render(context)
rendered += f"{inner_indent}{bullet} {content}\n"
return rendered


# A mapping from syntax tree node type to a function that renders it.
# This can be used to overwrite renderer functions of existing syntax
# or add support for new syntax.
RENDERERS: Mapping[str, Render] = {
"bullet_list": partial(_render_list, bullet="-"),
"ordered_list": partial(_render_list, bullet="1."),
last_indent = ""
indent_counter = 0

indent_lookup: Dict[str, int] = {}
for line in text.split(eol):
match = _RE_INDENT.match(line)
assert match is not None # for pylint
list_match = _RE_LIST_ITEM.match(match["content"])
new_line = line
if list_match:
new_bullet = "-" if list_match["bullet"] in {"-", "*"} else "1."
new_line = f'{new_bullet} {list_match["item"]}'

this_indent = match["indent"]
if this_indent:
indent_diff = len(this_indent) - len(last_indent)
if indent_diff == 0:
...
elif this_indent in indent_lookup:
indent_counter = indent_lookup[this_indent]
elif indent_diff > 0:
indent_counter += 1
indent_lookup[this_indent] = indent_counter
else:
raise NotImplementedError(f"Error in indentation of: `{line}`")
else:
indent_counter = 0
last_indent = match["indent"]
new_indent = indent * indent_counter
rendered += f"{new_indent}{new_line.strip()}{eol}"
return rendered.rstrip()


# # A mapping from syntax tree node type to a function that renders it.
# # This can be used to overwrite renderer functions of existing syntax
# # or add support for new syntax.
RENDERERS: Mapping[str, Render] = {}
POSTPROCESSORS = {
"bullet_list": _normalize_list,
"ordered_list": _normalize_list,
}
11 changes: 7 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,28 @@ classifiers = [
keywords = ["mdformat", "markdown", "markdown-it"]
requires-python = ">=3.7.2"
dependencies = [
"mdformat >=0.7.0,<0.8.0",
"mdit-py-plugins >=0.3.2",
"mdformat >= 0.7.16",
"mdformat-gfm >= 0.3.5",
"mdit-py-plugins[linkify] >= 0.3.3",
]
dynamic = ["version", "description"]

[project.optional-dependencies]
recommended = [
# Keep in-sync with README
"mdformat-admon",
"mdformat-beautysh",
"mdformat-black",
"mdformat-config",
"mdformat-footnote",
"mdformat-frontmatter",
"mdformat-gfm",
"mdformat-simple-breaks",
"mdformat-tables",
"mdformat-toc",
"mdformat-web",
]
test = [
"pytest>=6.0",
"pytest >= 7.0",
"pytest-cov",
]
dev = ["pre-commit"]
Expand Down
154 changes: 147 additions & 7 deletions tests/fixtures.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,28 +69,168 @@ Corrected Indentation from 5x
- item 4
.

FIXME: List with (what should be converted to a) code block
Handle Jagged Indents 2x
.
- item 1
- item 2
- item 3
- item 4
- item 5
- item 6
- item 7
- item 8
.
- item 1
- item 2
- item 3
- item 4
- item 5
- item 6
- item 7
- item 8
.

Handle Jagged Indents 5x
.
- item 1
- item 2
- item 3
- item 4
- item 5
- item 6
- item 7
- item 8
.
- item 1
- item 2
- item 3
- item 4
- item 5
- item 6
- item 7
- item 8
.

Handle Mixed Indents
.
- item 1
- item 2
- item 3
- item 4
- item 5
- item 6
- item 7
- item 8
.
- item 1
- item 2
- item 3
- item 4
- item 5
- item 6
- item 7
- item 8
.

List with (what should be converted to a) code block
.
- item 1

code block
.
- item 1

code block
code block
.

FIXME: List with explicit code block (that should keep indentation)
List with explicit code block (that should keep indentation)
.
- item 1

```
```txt
code block
```
.
- item 1
```
code block
```
```txt
code block
```
.
Table
.
| Label | Rating | Comment |
|:---------------|---------:|:---------------------|
| Name | 2| <!-- Comment --> |
.
| Label | Rating | Comment |
|:---------------|---------:|:---------------------|
| Name | 2| <!-- Comment --> |
.
Floating Link
.
> Based on [External Link]
[external link]: https://github.com/czuli/github-markdown-example/tree/7326f19c94be992319394e5bfeaa07b30f858e46
.
> Based on [External Link]
[external link]: https://github.com/czuli/github-markdown-example/tree/7326f19c94be992319394e5bfeaa07b30f858e46
.
Headings
.
# [h1] The largest heading
## [h2] heading
### [h3] heading
#### [h4] heading
##### [h5] heading
###### [h6] The smallest heading
.
# \[h1\] The largest heading
## \[h2\] heading
### \[h3\] heading
#### \[h4\] heading
##### \[h5\] heading
###### \[h6\] The smallest heading
.
Task List / Check List (WARN: escaping is prevented by mdformat-gfm. Tested by py#-hook)
.
- [x] #739
- [ ] Add delight to the experience when all tasks are complete :tada:
.
- \[x\] #739
- \[ \] Add delight to the experience when all tasks are complete :tada:
.
Footnotes (WARN: escaping is prevented by mdformat-gfm. Tested by py#-hook)
.
Here is a simple footnote[^1].
You can also use words, to fit your writing style more closely[^note].
[^1]: My reference.
[^note]: Named footnotes will still render with numbers instead of the text but allow easier identification and linking.\
This footnote also has been made with a different syntax using 4 spaces for new lines.
.
Here is a simple footnote\[^1\].
You can also use words, to fit your writing style more closely\[^note\].
\[^1\]: My reference.
\[^note\]: Named footnotes will still render with numbers instead of the text but allow easier identification and linking.\
This footnote also has been made with a different syntax using 4 spaces for new lines.
.
17 changes: 17 additions & 0 deletions tests/pre-commit-test-recommended.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Other Tests

## Footnotes

FYI: Requires `mdformat-footnote`:

Here is a simple footnote[^1].

A footnote can also have multiple lines[^2].

You can also use words, to fit your writing style more closely[^note].

[^1]: My reference.
[^2]: Every new line should be prefixed with 2 spaces.\
This allows you to have a footnote with multiple lines.
[^note]: Named footnotes will still render with numbers instead of the text but allow easier identification and linking.\
This footnote also has been made with a different syntax using 4 spaces for new lines.
Loading

0 comments on commit 15a3ec6

Please sign in to comment.