From 4948835fc0dc2953207d0ce10d6117fe34f49aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?= Date: Thu, 21 Nov 2024 05:57:33 +0100 Subject: [PATCH] Allow to customize directive names (#241) --- README.md | 14 +++++++ locale/es/README.md | 12 ++++++ locale/es/README.md.po | 3 ++ locale/fr/README.md | 12 ++++++ locale/fr/README.md.po | 3 ++ pyproject.toml | 2 +- src/mkdocs_include_markdown_plugin/config.py | 8 ++++ .../directive.py | 38 ++++++++++--------- src/mkdocs_include_markdown_plugin/event.py | 33 ++++++++++------ src/mkdocs_include_markdown_plugin/plugin.py | 26 ++++++------- tests/test_unit/test_config.py | 30 +++++++++++++++ tests/test_unit/test_exclude.py | 2 +- 12 files changed, 137 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 726c1cb..0182ab2 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,20 @@ You can include it in the installation of the plugin adding the `cache` extra: mkdocs-include-markdown-plugin[cache] ``` + + +#### `directives` + +Customize the names of the directives. + +```yaml +plugins: + - include-markdown: + directives: + include-markdown: include-md + include: replace +``` + ### Reference This plugin provides two directives, one to include Markdown files and another diff --git a/locale/es/README.md b/locale/es/README.md index b167809..d46a887 100644 --- a/locale/es/README.md +++ b/locale/es/README.md @@ -96,6 +96,18 @@ Puedes incluirla en la instalación del plugin añadiendo el extra `cache`: mkdocs-include-markdown-plugin[cache] ``` +#### `directives` + +Personaliza los nombres de las directivas. + +```yaml +plugins: + - include-markdown: + directives: + include-markdown: include-md + include: replace +``` + ### Referencia Este plugin provee dos directivas, una para incluir archivos Markdown y otra para diff --git a/locale/es/README.md.po b/locale/es/README.md.po index df818d5..16bcc87 100644 --- a/locale/es/README.md.po +++ b/locale/es/README.md.po @@ -451,3 +451,6 @@ msgid "" "[downloads-link]: https://pepy.tech/project/mkdocs-include-markdown-plugin" msgstr "" "[downloads-link]: https://pepy.tech/project/mkdocs-include-markdown-plugin" + +msgid "Customize the names of the directives." +msgstr "Personaliza los nombres de las directivas." diff --git a/locale/fr/README.md b/locale/fr/README.md index 2671139..3768766 100644 --- a/locale/fr/README.md +++ b/locale/fr/README.md @@ -96,6 +96,18 @@ supplément `cache`: mkdocs-include-markdown-plugin[cache] ``` +#### `directives` + +Personnaliser les noms des directives. + +```yaml +plugins: + - include-markdown: + directives: + include-markdown: include-md + include: replace +``` + ### Référence Ce plugin fournit deux directives, une pour inclure des fichiers Markdown et une diff --git a/locale/fr/README.md.po b/locale/fr/README.md.po index 17cbe55..be54f39 100644 --- a/locale/fr/README.md.po +++ b/locale/fr/README.md.po @@ -450,3 +450,6 @@ msgid "" "[downloads-link]: https://pepy.tech/project/mkdocs-include-markdown-plugin" msgstr "" "[downloads-link]: https://pepy.tech/project/mkdocs-include-markdown-plugin" + +msgid "Customize the names of the directives." +msgstr "Personnaliser les noms des directives." diff --git a/pyproject.toml b/pyproject.toml index 581d709..2293a2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mkdocs-include-markdown-plugin" -version = "7.0.1" +version = "7.1.0" description = "Mkdocs Markdown includer plugin." readme = "README.md" license = "Apache-2.0" diff --git a/src/mkdocs_include_markdown_plugin/config.py b/src/mkdocs_include_markdown_plugin/config.py index da8563b..7792b65 100644 --- a/src/mkdocs_include_markdown_plugin/config.py +++ b/src/mkdocs_include_markdown_plugin/config.py @@ -25,3 +25,11 @@ class PluginConfig(Config): # noqa: D101 exclude = ListOfItems(MkType(str), default=[]) cache = MkType(int, default=0) recursive = MkType(bool, default=True) + directives = MkType( + dict, + default={ + '__default': '', + 'include': 'include', + 'include-markdown': 'include-markdown', + }, + ) diff --git a/src/mkdocs_include_markdown_plugin/directive.py b/src/mkdocs_include_markdown_plugin/directive.py index 0e57356..2587ea9 100644 --- a/src/mkdocs_include_markdown_plugin/directive.py +++ b/src/mkdocs_include_markdown_plugin/directive.py @@ -2,6 +2,7 @@ from __future__ import annotations +import functools import os import re import stat @@ -74,11 +75,13 @@ class DirectiveBoolArgument: # noqa: D101 } +@functools.lru_cache def arg(arg: str) -> re.Pattern[str]: """Return a compiled regexp to match a boolean argument.""" return re.compile(rf'{arg}=([{RE_ESCAPED_PUNCTUATION}\w]*)') +@functools.lru_cache def str_arg(arg: str) -> re.Pattern[str]: """Return a compiled regexp to match a string argument.""" return re.compile( @@ -88,21 +91,23 @@ def str_arg(arg: str) -> re.Pattern[str]: ARGUMENT_REGEXES = { - 'start': str_arg('start'), - 'end': str_arg('end'), - 'exclude': str_arg('exclude'), - 'encoding': str_arg('encoding'), + 'start': functools.partial(str_arg, 'start'), + 'end': functools.partial(str_arg, 'end'), + 'exclude': functools.partial(str_arg, 'exclude'), + 'encoding': functools.partial(str_arg, 'encoding'), # bool - 'comments': arg('comments'), - 'preserve-includer-indent': arg('preserve-includer-indent'), - 'dedent': arg('dedent'), - 'trailing-newlines': arg('trailing-newlines'), - 'rewrite-relative-urls': arg('rewrite-relative-urls'), - 'recursive': arg('recursive'), + 'comments': functools.partial(arg, 'comments'), + 'preserve-includer-indent': functools.partial( + arg, 'preserve-includer-indent', + ), + 'dedent': functools.partial(arg, 'dedent'), + 'trailing-newlines': functools.partial(arg, 'trailing-newlines'), + 'rewrite-relative-urls': functools.partial(arg, 'rewrite-relative-urls'), + 'recursive': functools.partial(arg, 'recursive'), # int - 'heading-offset': arg('heading-offset'), + 'heading-offset': functools.partial(arg, 'heading-offset'), } INCLUDE_DIRECTIVE_ARGS = { @@ -111,8 +116,6 @@ def str_arg(arg: str) -> re.Pattern[str]: ) } -INCLUDE_MARKDOWN_DIRECTIVE_ARGS = set(ARGUMENT_REGEXES) - WARN_INVALID_DIRECTIVE_ARGS_REGEX = re.compile( rf'[\w-]*=[{RE_ESCAPED_PUNCTUATION}\w]*', ) @@ -128,12 +131,11 @@ def warn_invalid_directive_arguments( """Warns about the invalid arguments passed to a directive.""" valid_args = ( INCLUDE_DIRECTIVE_ARGS if directive == 'include' - else INCLUDE_MARKDOWN_DIRECTIVE_ARGS + else set(ARGUMENT_REGEXES) ) - for arg_match in WARN_INVALID_DIRECTIVE_ARGS_REGEX.finditer( + for arg_value in WARN_INVALID_DIRECTIVE_ARGS_REGEX.findall( arguments_string, ): - arg_value = arg_match.group() if arg_value.split('=', 1)[0] not in valid_args: location = process.file_lineno_message( page_src_path, docs_dir, directive_lineno(), @@ -173,7 +175,7 @@ def parse_string_argument(match: re.Match[str]) -> str | None: def create_include_tag( - opening_tag: str, closing_tag: str, tag: str = 'include', + opening_tag: str, closing_tag: str, tag: str, ) -> re.Pattern[str]: """Create a regex pattern to match an inclusion tag directive. @@ -200,7 +202,7 @@ def parse_bool_options( for option_name in option_names: bool_options[option_name] = DirectiveBoolArgument( value=defaults[option_name], # type: ignore - regex=ARGUMENT_REGEXES[option_name], + regex=ARGUMENT_REGEXES[option_name](), ) for arg_name, arg in bool_options.items(): diff --git a/src/mkdocs_include_markdown_plugin/event.py b/src/mkdocs_include_markdown_plugin/event.py index f63fd26..58eb317 100644 --- a/src/mkdocs_include_markdown_plugin/event.py +++ b/src/mkdocs_include_markdown_plugin/event.py @@ -18,6 +18,7 @@ from mkdocs_include_markdown_plugin.directive import ( ARGUMENT_REGEXES, GLOB_FLAGS, + create_include_tag, parse_bool_options, parse_filename_argument, parse_string_argument, @@ -133,7 +134,7 @@ def found_include_tag( # noqa: PLR0912, PLR0915 docs_dir, ) - exclude_match = ARGUMENT_REGEXES['exclude'].search(arguments_string) + exclude_match = ARGUMENT_REGEXES['exclude']().search(arguments_string) ignore_paths = [*settings_ignore_paths] if exclude_match is not None: exclude_string = parse_string_argument(exclude_match) @@ -186,7 +187,7 @@ def found_include_tag( # noqa: PLR0912, PLR0915 f' Possible values are true or false.', ) - start_match = ARGUMENT_REGEXES['start'].search(arguments_string) + start_match = ARGUMENT_REGEXES['start']().search(arguments_string) if start_match: start = parse_string_argument(start_match) if start is None: @@ -200,7 +201,7 @@ def found_include_tag( # noqa: PLR0912, PLR0915 else: start = defaults['start'] - end_match = ARGUMENT_REGEXES['end'].search(arguments_string) + end_match = ARGUMENT_REGEXES['end']().search(arguments_string) if end_match: end = parse_string_argument(end_match) if end is None: @@ -214,7 +215,8 @@ def found_include_tag( # noqa: PLR0912, PLR0915 else: end = defaults['end'] - encoding_match = ARGUMENT_REGEXES['encoding'].search(arguments_string) + encoding_match = ARGUMENT_REGEXES['encoding']().search( + arguments_string) if encoding_match: encoding = parse_string_argument(encoding_match) if encoding is None: @@ -344,7 +346,7 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 docs_dir, ) - exclude_match = ARGUMENT_REGEXES['exclude'].search(arguments_string) + exclude_match = ARGUMENT_REGEXES['exclude']().search(arguments_string) ignore_paths = [*settings_ignore_paths] if exclude_match is not None: exclude_string = parse_string_argument(exclude_match) @@ -400,7 +402,7 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 ) # start and end arguments - start_match = ARGUMENT_REGEXES['start'].search(arguments_string) + start_match = ARGUMENT_REGEXES['start']().search(arguments_string) if start_match: start = parse_string_argument(start_match) if start is None: @@ -414,7 +416,7 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 else: start = defaults['start'] - end_match = ARGUMENT_REGEXES['end'].search(arguments_string) + end_match = ARGUMENT_REGEXES['end']().search(arguments_string) if end_match: end = parse_string_argument(end_match) if end is None: @@ -428,7 +430,8 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 else: end = defaults['end'] - encoding_match = ARGUMENT_REGEXES['encoding'].search(arguments_string) + encoding_match = ARGUMENT_REGEXES['encoding']().search( + arguments_string) if encoding_match: encoding = parse_string_argument(encoding_match) if encoding is None: @@ -443,7 +446,7 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 encoding = defaults['encoding'] # heading offset - offset_match = ARGUMENT_REGEXES['heading-offset'].search( + offset_match = ARGUMENT_REGEXES['heading-offset']().search( arguments_string, ) if offset_match: @@ -633,8 +636,16 @@ def on_page_markdown( page.file.abs_src_path, docs_dir, { - 'include': plugin._include_tag(), - 'include-markdown': plugin._include_markdown_tag(), + 'include': create_include_tag( + config.opening_tag, + config.closing_tag, + config.directives.get('include', 'include'), + ), + 'include-markdown': create_include_tag( + config.opening_tag, + config.closing_tag, + config.directives.get('include-markdown', 'include-markdown'), + ), }, { 'encoding': config.encoding, diff --git a/src/mkdocs_include_markdown_plugin/plugin.py b/src/mkdocs_include_markdown_plugin/plugin.py index 9c8dd5c..602cc0c 100644 --- a/src/mkdocs_include_markdown_plugin/plugin.py +++ b/src/mkdocs_include_markdown_plugin/plugin.py @@ -11,7 +11,6 @@ if TYPE_CHECKING: # pragma: no cover - import re from mkdocs.config.defaults import MkDocsConfig from mkdocs.livereload import LiveReloadServer @@ -20,7 +19,6 @@ from mkdocs_include_markdown_plugin.cache import Cache, initialize_cache from mkdocs_include_markdown_plugin.config import PluginConfig -from mkdocs_include_markdown_plugin.directive import create_include_tag from mkdocs_include_markdown_plugin.event import ( on_page_markdown as _on_page_markdown, ) @@ -44,20 +42,18 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: cache.clean() self._cache = cache - return config - - def _include_tag(self) -> re.Pattern[str]: - return create_include_tag( - self.config.opening_tag, - self.config.closing_tag, - ) + if '__default' not in self.config.directives: # pragma: no cover + for directive in self.config.directives: + if directive not in { + 'include', 'include-markdown', + }: + raise PluginError( + f"Invalid directive name '{directive}' at 'directives'" + ' global setting. Valid values are "include" and' + ' "include-markdown".', + ) - def _include_markdown_tag(self) -> re.Pattern[str]: - return create_include_tag( - self.config.opening_tag, - self.config.closing_tag, - tag='include-markdown', - ) + return config @cached_property def _files_watcher(self) -> FilesWatcher: diff --git a/tests/test_unit/test_config.py b/tests/test_unit/test_config.py index 324e86a..a661226 100644 --- a/tests/test_unit/test_config.py +++ b/tests/test_unit/test_config.py @@ -152,6 +152,36 @@ def _run_test( {}, id='custom-comments', ), + + # directives + pytest.param( + '{% foo "{filepath}" %}bar\n', + 'baz\n', + 'baz\nbar\n', + {'comments': False, 'directives': {'include-markdown': 'foo'}}, + id='custom-include-markdown-directive', + ), + pytest.param( + '{% my-include "{filepath}" %}bar\n', + 'baz\n', + 'baz\nbar\n', + {'comments': False, 'directives': {'include': 'my-include'}}, + id='custom-include-directive', + ), + pytest.param( + '{% foo "{filepath}" %}bar\n{% include-markdown "{filepath}" %}', + 'baz\n', + '{% foo "{filepath}" %}bar\nbaz\n', + {'comments': False, 'directives': {'non-existent': 'foo'}}, + id='default-include-markdown-directive', + ), + pytest.param( + '{% foo "{filepath}" %}bar\n{% include "{filepath}" %}', + 'baz\n', + '{% foo "{filepath}" %}bar\nbaz\n', + {'comments': False, 'directives': {'non-existent': 'foo'}}, + id='default-include-directive', + ), ), indirect=['plugin'], ) diff --git a/tests/test_unit/test_exclude.py b/tests/test_unit/test_exclude.py index f0681d5..edea155 100644 --- a/tests/test_unit/test_exclude.py +++ b/tests/test_unit/test_exclude.py @@ -1,4 +1,4 @@ -"""Tests for mkdocs-include-markdown-plugin `exclude` directives argument.""" +"""Tests for mkdocs-include-markdown-plugin `exclude` setting.""" import functools import os