Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support real world use cases #1

Merged
merged 19 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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