diff --git a/README.md b/README.md
index a4130eb..6393c7f 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,7 @@ plugins:
heading_offset: 0
start:
end:
+ recursive: true
```
#### `opening_tag` and `closing_tag`
@@ -245,6 +246,9 @@ Includes the content of a file or a group of files.
- #
**encoding** (_utf-8_): Specify the encoding of the included file.
If not defined `utf-8` will be used.
+- #
+ **recursive** (_true_): When this option is disabled, included files are not
+ processed for recursive includes. Possible values are `true` and `false`.
##### Examples
diff --git a/locale/es/README.md b/locale/es/README.md
index 006c8af..fd93fa1 100644
--- a/locale/es/README.md
+++ b/locale/es/README.md
@@ -48,6 +48,7 @@ plugins:
heading_offset: 0
start:
end:
+ recursive: true
```
#### `opening_tag` y `closing_tag`
@@ -236,6 +237,10 @@ Los valores posibles son `true` y `false`.
- # **encoding**
(*utf-8*): Especifica la codificación del archivo incluído. Si no se define,
se usará `utf-8`.
+- # **recursive** (*true*):
+Cuando esta opción está deshabilitada, los archivos incluidos no son
+procesados para incluir de forma recursiva. Los valores posibles son `true` y
+`false`.
##### Ejemplos
diff --git a/locale/es/README.md.po b/locale/es/README.md.po
index 6cb4a9e..fa593f6 100644
--- a/locale/es/README.md.po
+++ b/locale/es/README.md.po
@@ -406,3 +406,13 @@ msgstr ""
msgid "[pypi-link]: https://pypi.org/project/mkdocs-include-markdown-plugin"
msgstr "[pypi-link]: https://pypi.org/project/mkdocs-include-markdown-plugin"
+
+msgid ""
+"# **recursive** "
+"(*true*): When this option is disabled, included files are not processed for"
+" recursive includes. Possible values are `true` and `false`."
+msgstr ""
+"# **recursive** "
+"(*true*): Cuando esta opción está deshabilitada, los archivos incluidos no "
+"son procesados para incluir de forma recursiva. Los valores posibles son "
+"`true` y `false`."
diff --git a/locale/fr/README.md b/locale/fr/README.md
index 2caeee1..6237c73 100644
--- a/locale/fr/README.md
+++ b/locale/fr/README.md
@@ -47,6 +47,7 @@ plugins:
heading_offset: 0
start:
end:
+ recursive: true
```
#### `opening_tag` et `closing_tag`
@@ -235,6 +236,9 @@ valeurs possibles sont `true` et `false`.
- # **encoding**
(*utf-8*): Spécifiez l'encodage du fichier inclus. S'il n'est pas défini,
`utf-8` sera utilisé.
+- # **recursive** (*true*):
+Lorsque cette option est désactivée, les fichiers inclus ne sont pas traités
+pour des inclusions récursives. Les valeurs possibles sont `true` et `false`.
##### Exemples
diff --git a/locale/fr/README.md.po b/locale/fr/README.md.po
index 20c3964..dd59dfa 100644
--- a/locale/fr/README.md.po
+++ b/locale/fr/README.md.po
@@ -402,6 +402,15 @@ msgid ""
msgstr ""
"[Globs génériques Bash]: https://facelessuser.github.io/wcmatch/glob/#syntax"
-#, fuzzy
msgid "[pypi-link]: https://pypi.org/project/mkdocs-include-markdown-plugin"
msgstr "[pypi-link]: https://pypi.org/project/mkdocs-include-markdown-plugin"
+
+msgid ""
+"# **recursive** "
+"(*true*): When this option is disabled, included files are not processed for"
+" recursive includes. Possible values are `true` and `false`."
+msgstr ""
+"# **recursive** "
+"(*true*): Lorsque cette option est désactivée, les fichiers inclus ne sont "
+"pas traités pour des inclusions récursives. Les valeurs possibles sont "
+"`true` et `false`."
diff --git a/pyproject.toml b/pyproject.toml
index 32ddb17..573a040 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "mkdocs-include-markdown-plugin"
-version = "6.0.7"
+version = "6.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 251f55c..a633428 100644
--- a/src/mkdocs_include_markdown_plugin/config.py
+++ b/src/mkdocs_include_markdown_plugin/config.py
@@ -24,3 +24,4 @@ class PluginConfig(Config): # noqa: D101
end = Optional(MkType(str))
exclude = ListOfItems(MkType(str), default=[])
cache = MkType(int, default=0)
+ recursive = MkType(bool, default=True)
diff --git a/src/mkdocs_include_markdown_plugin/directive.py b/src/mkdocs_include_markdown_plugin/directive.py
index 4c8a432..89e0f17 100644
--- a/src/mkdocs_include_markdown_plugin/directive.py
+++ b/src/mkdocs_include_markdown_plugin/directive.py
@@ -34,6 +34,7 @@ class DirectiveBoolArgument: # noqa: D101
'comments': bool,
'rewrite-relative-urls': bool,
'heading-offset': int,
+ 'recursive': bool,
'start': str | None,
'end': str | None,
},
@@ -96,6 +97,7 @@ def str_arg(arg: str) -> re.Pattern[str]:
'dedent': arg('dedent'),
'trailing-newlines': arg('trailing-newlines'),
'rewrite-relative-urls': arg('rewrite-relative-urls'),
+ 'recursive': arg('recursive'),
# int
'heading-offset': arg('heading-offset'),
diff --git a/src/mkdocs_include_markdown_plugin/event.py b/src/mkdocs_include_markdown_plugin/event.py
index f390c92..d284ac1 100644
--- a/src/mkdocs_include_markdown_plugin/event.py
+++ b/src/mkdocs_include_markdown_plugin/event.py
@@ -103,6 +103,22 @@ def get_file_content( # noqa: PLR0913, PLR0915
http_cache: Cache | None = None,
) -> str:
"""Return the content of the file to include."""
+ settings_ignore_paths = []
+ if settings.exclude is not None:
+ for path in glob.glob(
+ [
+ os.path.join(docs_dir, fp)
+ if not os.path.isabs(fp)
+ else fp for fp in settings.exclude
+ ],
+ flags=GLOB_FLAGS,
+ root_dir=docs_dir,
+ ):
+ if path not in settings_ignore_paths:
+ settings_ignore_paths.append(path)
+ if page_src_path in settings_ignore_paths:
+ return markdown
+
def found_include_tag( # noqa: PLR0912, PLR0915
match: re.Match[str],
) -> str:
@@ -125,19 +141,7 @@ def found_include_tag( # noqa: PLR0912, PLR0915
arguments_string = match['arguments']
exclude_match = ARGUMENT_REGEXES['exclude'].search(arguments_string)
- ignore_paths = []
- if settings.exclude:
- ignore_paths.extend(
- glob.glob(
- [
- os.path.join(docs_dir, fp)
- if not os.path.isabs(fp)
- else fp for fp in settings.exclude
- ],
- flags=GLOB_FLAGS,
- root_dir=docs_dir,
- ),
- )
+ ignore_paths = [*settings_ignore_paths]
if exclude_match is not None:
exclude_string = parse_string_argument(exclude_match)
if exclude_string is None:
@@ -151,14 +155,13 @@ def found_include_tag( # noqa: PLR0912, PLR0915
f' {file_lineno_message(page_src_path, docs_dir, lineno)}',
)
- ignore_paths.extend(
- resolve_file_paths_to_exclude(
+ for path in resolve_file_paths_to_exclude(
exclude_string,
page_src_path,
docs_dir,
- ),
- )
- ignore_paths = list(set(ignore_paths))
+ ):
+ if path not in ignore_paths:
+ ignore_paths.append(path)
file_paths_to_include, is_url = resolve_file_paths_to_include(
filename,
@@ -181,7 +184,8 @@ def found_include_tag( # noqa: PLR0912, PLR0915
files_watcher.included_files.extend(file_paths_to_include)
bool_options, invalid_bool_args = parse_bool_options(
- ['preserve-includer-indent', 'dedent', 'trailing-newlines'],
+ ['preserve-includer-indent', 'dedent',
+ 'trailing-newlines', 'recursive'],
defaults,
arguments_string,
)
@@ -264,16 +268,17 @@ def found_include_tag( # noqa: PLR0912, PLR0915
expected_but_any_found[i] = False
# nested includes
- new_text_to_include = get_file_content(
- new_text_to_include,
- file_path,
- docs_dir,
- tags,
- defaults,
- settings,
- files_watcher=files_watcher,
- http_cache=http_cache,
- )
+ if bool_options['recursive'].value:
+ new_text_to_include = get_file_content(
+ new_text_to_include,
+ file_path,
+ docs_dir,
+ tags,
+ defaults,
+ settings,
+ files_watcher=files_watcher,
+ http_cache=http_cache,
+ )
# trailing newlines right stripping
if not bool_options['trailing-newlines'].value:
@@ -349,19 +354,7 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915
arguments_string = match['arguments']
exclude_match = ARGUMENT_REGEXES['exclude'].search(arguments_string)
- ignore_paths = []
- if settings.exclude is not None:
- ignore_paths.extend(
- glob.glob(
- [
- os.path.join(docs_dir, fp)
- if not os.path.isabs(fp)
- else fp for fp in settings.exclude
- ],
- flags=GLOB_FLAGS,
- root_dir=docs_dir,
- ),
- )
+ ignore_paths = [*settings_ignore_paths]
if exclude_match is not None:
exclude_string = parse_string_argument(exclude_match)
if exclude_string is None:
@@ -374,14 +367,13 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915
f' directive at'
f' {file_lineno_message(page_src_path, docs_dir, lineno)}',
)
- ignore_paths.extend(
- resolve_file_paths_to_exclude(
+ for path in resolve_file_paths_to_exclude(
exclude_string,
page_src_path,
docs_dir,
- ),
- )
- ignore_paths = list(set(ignore_paths))
+ ):
+ if path not in ignore_paths:
+ ignore_paths.append(path)
file_paths_to_include, is_url = resolve_file_paths_to_include(
filename,
@@ -667,6 +659,7 @@ def on_page_markdown(
'comments': config.comments,
'rewrite-relative-urls': config.rewrite_relative_urls,
'heading-offset': config.heading_offset,
+ 'recursive': config.recursive,
'start': config.start,
'end': config.end,
},
diff --git a/tests/test_unit/test_nested_includes.py b/tests/test_unit/test_nested_includes.py
index c2689c4..bd77777 100644
--- a/tests/test_unit/test_nested_includes.py
+++ b/tests/test_unit/test_nested_includes.py
@@ -226,6 +226,32 @@
],
id='start-end-not-found (second-level)',
),
+ # recursive inclusion disabled with `include` directive
+ pytest.param(
+ '''# Header
+
+{%
+ include "{filepath}"
+ comments=false
+ recursive=false
+%}''',
+ '''# Header 2
+
+{% include "{filepath}" %}
+''',
+ '''# Header 3
+
+This content must not be included.
+''',
+ '''# Header
+
+# Header 2
+
+{% include "{filepath}" %}
+''',
+ [],
+ id='include-recursive=false',
+ ),
),
)
def test_nested_include(
@@ -249,6 +275,9 @@ def test_nested_include(
second_includer_content = second_includer_content.replace(
'{filepath}', included_file.as_posix(),
)
+ expected_result = expected_result.replace(
+ '{filepath}', included_file.as_posix(),
+ )
first_includer_file.write_text(first_includer_content)
second_includer_file.write_text(second_includer_content)