Skip to content
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
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ not RELEASE

### Rules

- `<!--- #if A B -->` is true when the configured `symbol` is exactly one of the listed names
- `symbol` defines one or more symbols: `DEBUG`, `DEBUG RELEASE`, `DEBUG|RELEASE`, or a list
`[DEBUG, RELEASE]`. With no `symbol` configured, every `#if` is false.
- `<!--- #if A B -->` is true when any defined symbol is exactly one of the listed names
(`DEBUG` does not match `DEBUG_X`). Names are separated by spaces and/or `|`, so
`#if A | B` and `#if A|B` mean the same. With no `symbol` configured, every `#if` is false.
`#if A | B` and `#if A|B` mean the same.
- `#else` is optional; nested `#if` blocks are not supported.
- Malformed blocks (unclosed `#if`, stray `#else` / `#endif`, duplicate `#else`, nesting) raise
`md_condition.ConditionSyntaxError` with the offending line number.
Expand All @@ -53,3 +55,11 @@ markdown_extensions:
- md_condition:
symbol: DEBUG
```

To define several symbols at once:

```yaml
markdown_extensions:
- md_condition:
symbol: [DEBUG, RELEASE]
```
2 changes: 1 addition & 1 deletion md_condition/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class ConditionExtension(Extension):
def __init__(self, **kwargs) -> None:
self.config = {
"symbol": ["", "Condition symbol"],
"symbol": ["", "Defined symbol(s): a string separated by spaces/`|`, or a list"],
}
super().__init__(**kwargs)

Expand Down
9 changes: 6 additions & 3 deletions md_condition/preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ class ConditionPreprocessor(Preprocessor):

def __init__(self, md: Markdown, extension: ConditionExtension) -> None:
super().__init__(md)
self.symbol = extension.getConfig("symbol")
# `symbol` is a string ("DEBUG", "DEBUG RELEASE", "DEBUG|RELEASE") or a list of them
symbol = extension.getConfig("symbol") or ""
values = [symbol] if isinstance(symbol, str) else symbol
self.symbols = {name for value in values for name in self.RE_NAME.findall(str(value))}

def run(self, lines: list[str]) -> list[str]:
new_lines = []
Expand All @@ -43,8 +46,8 @@ def run(self, lines: list[str]) -> list[str]:
)
block_start = number
seen_else = False
# `#if A B` / `#if A | B` is true when the symbol is one of the listed names
keep = self.symbol in self.RE_NAME.findall(start.group(1))
# `#if A B` / `#if A | B` is true when any configured symbol is listed
keep = not self.symbols.isdisjoint(self.RE_NAME.findall(start.group(1)))
continue
if self.RE_ELSE.match(line):
if block_start is None:
Expand Down
50 changes: 50 additions & 0 deletions tests/test_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,47 @@ def test_symbol_is_matched_as_whole_name(symbol: str, condition: str, kept: bool
assert output == ("<p>yes</p>" if kept else "<p>no</p>")


ISSUE_6_SOURCE = """\
# 1
<!--- #if DEBUG -->
DEBUG
<!--- #else -->
No DEBUG
<!--- #endif -->
# 2
<!--- #if RELEASE -->
RELEASE
<!--- #else -->
No RELEASE
<!--- #endif -->"""


@pytest.mark.parametrize(
("symbol", "debug", "release"),
[
# Issue #6: multiple defined symbols, each usable as its own condition
pytest.param("DEBUG RELEASE", True, True, id="space_separated"),
pytest.param("DEBUG|RELEASE", True, True, id="pipe_separated"),
pytest.param(["DEBUG", "RELEASE"], True, True, id="list"),
pytest.param(("DEBUG",), True, False, id="tuple"),
pytest.param("RELEASE", False, True, id="single"),
pytest.param([], False, False, id="empty_list"),
pytest.param(None, False, False, id="none"),
],
)
def test_multiple_symbols(symbol, debug: bool, release: bool) -> None:
md = markdown.Markdown(extensions=[ConditionExtension(symbol=symbol)])
expected = "<h1>1</h1>\n<p>{}</p>\n<h1>2</h1>\n<p>{}</p>".format(
"DEBUG" if debug else "No DEBUG", "RELEASE" if release else "No RELEASE"
)
assert md.convert(ISSUE_6_SOURCE) == expected


def test_multiple_symbols_any_listed_name_matches() -> None:
md = markdown.Markdown(extensions=[ConditionExtension(symbol=["DEBUG", "STAGING"])])
assert md.convert("<!--- #if RELEASE STAGING -->\nyes\n<!--- #endif -->") == "<p>yes</p>"


@pytest.mark.parametrize(
("source", "message"),
[
Expand Down Expand Up @@ -177,3 +218,12 @@ def test_make_extension_by_name() -> None:
},
)
assert md.convert("<!--- #if DEBUG -->\nyes\n<!--- #endif -->") == "<p>yes</p>"


def test_make_extension_by_name_with_list() -> None:
# MkDocs passes YAML lists through as Python lists
md = markdown.Markdown(
extensions=["md_condition"],
extension_configs={"md_condition": {"symbol": ["DEBUG", "RELEASE"]}},
)
assert md.convert("<!--- #if RELEASE -->\nyes\n<!--- #endif -->") == "<p>yes</p>"
Loading