Skip to content

Commit

Permalink
V1.9.0 Convert Obsidian callout aliases option
Browse files Browse the repository at this point in the history
See #4, behavior is enabled by default
  • Loading branch information
sondregronas committed Jan 25, 2023
1 parent 5611be2 commit a973ed7
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 8 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,12 @@ The following also works, but Obsidian may not render the block type correctly.
> [!INFO inline end] --> !!! info inline end
```
To get more information about inline blocks, or how to add your own custom callout blocks, check the [Material Mkdocs Documentation](https://squidfunk.github.io/mkdocs-material/reference/admonitions/#inline-blocks).
### Aliases
Obsidian allows the use of [aliases when creating callouts](https://help.obsidian.md/How+to/Use+callouts#Types), mkdocs-callouts converts these to the corresponding block type. Should you wish to disable this behaviour then you can do so by setting `aliases` to `false` in the plugin configuration:
```yaml
plugins:
- search
- callouts:
aliases: false
```
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "mkdocs-callouts"
version = "1.8.1"
version = "1.9.0"
keywords = ["mkdocs", "mkdocs-plugin", "markdown", "callouts", "admonitions", "obsidian"]
description = "A simple plugin that converts Obsidian style callouts and converts them into mkdocs supported 'admonitions' (a.k.a. callouts)."
readme = "README.md"
Expand Down
10 changes: 9 additions & 1 deletion src/mkdocs_callouts/plugin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from mkdocs.plugins import BasePlugin
from mkdocs.config import config_options

from mkdocs_callouts.utils import CalloutParser

Expand All @@ -16,5 +17,12 @@ class CalloutsPlugin(BasePlugin):
Allowing you to edit your notes
with confidence using Obsidian.
"""
config_scheme = { # pragma: no cover
('aliases', config_options.Type(bool, default=True))
}

def on_page_markdown(self, markdown, page, config, files):
return CalloutParser().parse(markdown)
parser = CalloutParser(
convert_aliases=self.config.get('aliases', True)
)
return parser.parse(markdown)
35 changes: 29 additions & 6 deletions src/mkdocs_callouts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,24 @@


class CalloutParser:
def __init__(self):
# From https://help.obsidian.md/How+to/Use+callouts#Types
aliases = {
'abstract': ['summary', 'tldr'],
'tip': ['hint', 'important'],
'success': ['check', 'done'],
'question': ['help', 'faq'],
'warning': ['caution', 'attention'],
'failure': ['fail', 'missing'],
'danger': ['error'],
'quote': ['cite']
}
alias_tuples = [(alias, c_type) for c_type, aliases in aliases.items() for alias in aliases]

def __init__(self, convert_aliases: bool = True):
self.active_callout: bool = False
self.convert_aliases: bool = convert_aliases

@staticmethod
def _parse_block_syntax(block) -> str:
def _parse_block_syntax(self, block) -> str:
"""Converts the callout syntax from obsidian into the mkdocs syntax
Takes an argument block, which is a regex match.
"""
Expand All @@ -25,9 +38,12 @@ def _parse_block_syntax(block) -> str:

# Group 2: Callout block type (note, warning, info, etc.) + inline block syntax
c_type = block.group(2).lower()
c_type = re.sub(r' ?\| *(inline|left) *$', ' inline', c_type)
c_type = re.sub(r' ?\| *(inline end|right) *$', ' inline end', c_type)
c_type = re.sub(r' ?\|.*', '', c_type)
c_type = re.sub(r' *\| *(inline|left) *$', ' inline', c_type)
c_type = re.sub(r' *\| *(inline end|right) *$', ' inline end', c_type)
c_type = re.sub(r' *\|.*', '', c_type)
# Convert aliases, if enabled
if self.convert_aliases:
c_type = self._convert_aliases(c_type)

# Group 3: Foldable callouts
syntax = {'-': '???', '+': '???+'}
Expand All @@ -40,6 +56,13 @@ def _parse_block_syntax(block) -> str:
# Construct the new callout syntax ({indent}!!! note "Title")
return f'{indent}{syntax} {c_type}{title}'

@staticmethod
def _convert_aliases(c_type: str) -> str:
"""Converts aliases to their respective callout type, if its enabled"""
for alias, identifier in CalloutParser.alias_tuples:
c_type = re.sub(rf'^{alias}\b', identifier, c_type)
return c_type

def _convert_block(self, line: str) -> str:
"""Calls parse_block_syntax if regex matches, which returns a converted callout block"""
match = re.search(CALLOUT_BLOCK_REGEX, line)
Expand Down
48 changes: 48 additions & 0 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest

from mkdocs_callouts.plugin import CalloutsPlugin
from mkdocs_callouts.utils import CalloutParser


def convert(input: str) -> str:
Expand Down Expand Up @@ -138,3 +139,50 @@ def test_folded_callouts():
mkdown = '> [!INFO]+\n> Folded content'
result = '???+ info\n\tFolded content'
assert (convert(mkdown) == result)


def test_aliases_enabled():
parser = CalloutParser(convert_aliases=True)

# Test alias conversion
mkdown = '> [!HINT]\n> Text'
result = '!!! tip\n\tText'
assert (parser.parse(mkdown) == result)

# Test alias conversion with inline block syntax
mkdown = '> [!HINT | inline]\n> Text'
result = '!!! tip inline\n\tText'
assert (parser.parse(mkdown) == result)

# Test alias conversion where alias is a substring of another alias
mkdown = '> [!checking]\n> Text'
unexpected = '!!! successing\n\tText'
result = '!!! checking\n\tText'
assert (parser.parse(mkdown) == result)
assert (parser.parse(mkdown) != unexpected)

# Test alias conversion where alias is a substring of another alias, with inline block syntax
mkdown = '> [!checking | inline]\n> Text'
unexpected = '!!! successing inline\n\tText'
result = '!!! checking inline\n\tText'
assert (parser.parse(mkdown) == result)
assert (parser.parse(mkdown) != unexpected)

# Test alias where first word is not an alias
mkdown = '> [!A HINT]\n> Text'
result = '!!! a hint\n\tText'
assert (parser.parse(mkdown) == result)

mkdown = '> [!A_HINT]\n> Text'
result = '!!! a_hint\n\tText'
assert (parser.parse(mkdown) == result)


def test_aliases_disabled():
parser = CalloutParser(convert_aliases=False)

mkdown = '> [!HINT]\n> Text'
unexpected = '!!! tip\n\tText'
result = '!!! hint\n\tText'
assert (parser.parse(mkdown) == result)
assert (parser.parse(mkdown) != unexpected)

0 comments on commit a973ed7

Please sign in to comment.