diff --git a/README.md b/README.md index 6393c7f..67b6624 100644 --- a/README.md +++ b/README.md @@ -177,42 +177,42 @@ content to include. ```jinja {% - include-markdown "../README.md" - start="" - end="" + include-markdown "../README.md" + start="" + end="" %} ``` ```jinja {% - include-markdown 'includes/header.md' - start='' - end='' - rewrite-relative-urls=false - comments=false + include-markdown 'includes/header.md' + start='' + end='' + rewrite-relative-urls=false + comments=false %} ``` ```jinja {% - include-markdown "includes/header.md" - heading-offset=1 + include-markdown "includes/header.md" + heading-offset=1 %} ``` ```jinja {% - include-markdown "../LICENSE*" - start="" - end='' - exclude="../*.rst" + include-markdown "../LICENSE*" + start="" + end='' + exclude="../*.rst" %} ``` ```jinja {% - include-markdown "**" - exclude="./{index,LICENSE}.md" + include-markdown "**" + exclude="./{index,LICENSE}.md" %} ``` @@ -260,16 +260,16 @@ Includes the content of a file or a group of files. ```jinja {% - include "../examples.md" - start="~~~yaml" - end="~~~\n" + include "../examples.md" + start="~~~yaml" + end="~~~\n" %} ``` ```jinja {% - include '**' - exclude='./*.md' + include '**' + exclude='./*.md' %} ``` diff --git a/locale/es/README.md b/locale/es/README.md index fd93fa1..b5c7856 100644 --- a/locale/es/README.md +++ b/locale/es/README.md @@ -168,42 +168,42 @@ especificado. Sólo soporta la sintaxis de encabezado de caracteres de hash ```jinja {% - include-markdown "../README.md" - start="" - end="" + include-markdown "../README.md" + start="" + end="" %} ``` ```jinja {% - include-markdown 'includes/header.md' - start='' - end='' - rewrite-relative-urls=false - comments=false + include-markdown 'includes/header.md' + start='' + end='' + rewrite-relative-urls=false + comments=false %} ``` ```jinja {% - include-markdown "includes/header.md" - heading-offset=1 + include-markdown "includes/header.md" + heading-offset=1 %} ``` ```jinja {% - include-markdown "../LICENSE*" - start="" - end='' - exclude="../*.rst" + include-markdown "../LICENSE*" + start="" + end='' + exclude="../*.rst" %} ``` ```jinja {% - include-markdown "**" - exclude="./{index,LICENSE}.md" + include-markdown "**" + exclude="./{index,LICENSE}.md" %} ``` @@ -252,16 +252,16 @@ procesados para incluir de forma recursiva. Los valores posibles son `true` y ```jinja {% - include "../examples.md" - start="~~~yaml" - end="~~~\n" + include "../examples.md" + start="~~~yaml" + end="~~~\n" %} ``` ```jinja {% - include '**' - exclude='./*.md' + include '**' + exclude='./*.md' %} ``` diff --git a/locale/fr/README.md b/locale/fr/README.md index 6237c73..0e6dee0 100644 --- a/locale/fr/README.md +++ b/locale/fr/README.md @@ -168,42 +168,42 @@ négatives pour supprimer les caractères `#` de tête. ```jinja {% - include-markdown "../README.md" - start="" - end="" + include-markdown "../README.md" + start="" + end="" %} ``` ```jinja {% - include-markdown 'includes/header.md' - start='' - end='' - rewrite-relative-urls=false - comments=false + include-markdown 'includes/header.md' + start='' + end='' + rewrite-relative-urls=false + comments=false %} ``` ```jinja {% - include-markdown "includes/header.md" - heading-offset=1 + include-markdown "includes/header.md" + heading-offset=1 %} ``` ```jinja {% - include-markdown "../LICENSE*" - start="" - end='' - exclude="../*.rst" + include-markdown "../LICENSE*" + start="" + end='' + exclude="../*.rst" %} ``` ```jinja {% - include-markdown "**" - exclude="./{index,LICENSE}.md" + include-markdown "**" + exclude="./{index,LICENSE}.md" %} ``` @@ -250,16 +250,16 @@ pour des inclusions récursives. Les valeurs possibles sont `true` et `false`. ```jinja {% - include "../examples.md" - start="~~~yaml" - end="~~~\n" + include "../examples.md" + start="~~~yaml" + end="~~~\n" %} ``` ```jinja {% - include '**' - exclude='./*.md' + include '**' + exclude='./*.md' %} ``` diff --git a/pyproject.toml b/pyproject.toml index f0ba866..269b4e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mkdocs-include-markdown-plugin" -version = "6.1.1" +version = "6.1.2" description = "Mkdocs Markdown includer plugin." readme = "README.md" license = "Apache-2.0" diff --git a/src/mkdocs_include_markdown_plugin/directive.py b/src/mkdocs_include_markdown_plugin/directive.py index 89e0f17..22ea614 100644 --- a/src/mkdocs_include_markdown_plugin/directive.py +++ b/src/mkdocs_include_markdown_plugin/directive.py @@ -12,6 +12,7 @@ from wcmatch import glob from mkdocs_include_markdown_plugin import process +from mkdocs_include_markdown_plugin.logger import logger @dataclass @@ -21,7 +22,7 @@ class DirectiveBoolArgument: # noqa: D101 if TYPE_CHECKING: - from typing import TypedDict + from typing import Literal, TypedDict DirectiveBoolArgumentsDict = dict[str, DirectiveBoolArgument] @@ -44,8 +45,8 @@ class DirectiveBoolArgument: # noqa: D101 GLOB_FLAGS = glob.NEGATE | glob.EXTGLOB | glob.GLOBSTAR | glob.BRACE RE_ESCAPED_PUNCTUATION = re.escape(string.punctuation) -DOUBLE_QUOTED_STR_RE = r'([^"]|(?<=\\)["])+' -SINGLE_QUOTED_STR_RE = r"([^']|(?<=\\)['])+" +DOUBLE_QUOTED_STR_RE = r'([^"]|(?<=\\)")+' +SINGLE_QUOTED_STR_RE = r"([^']|(?<=\\)')+" # In the following regular expression, the substrings "$OPENING_TAG" # and "$CLOSING_TAG" will be replaced by the effective opening and @@ -103,6 +104,40 @@ def str_arg(arg: str) -> re.Pattern[str]: 'heading-offset': arg('heading-offset'), } +INCLUDE_DIRECTIVE_ARGS = { + key for key in ARGUMENT_REGEXES if key not in ( + 'rewrite-relative-urls', 'heading-offset', 'comments', + ) +} + +INCLUDE_MARKDOWN_DIRECTIVE_ARGS = { + key for key in ARGUMENT_REGEXES if key != 'recursive' +} + + +def warn_invalid_directive_arguments( + arguments_string: str, + directive_lineno: int, + directive: Literal['include', 'include-markdown'], + page_src_path: str | None, + docs_dir: str, +) -> None: + """Warns about the invalid arguments passed to a directive.""" + arg_re = re.compile(rf'[\w-]*=[{RE_ESCAPED_PUNCTUATION}\w]*') + valid_args = ( + INCLUDE_DIRECTIVE_ARGS if directive == 'include' + else INCLUDE_MARKDOWN_DIRECTIVE_ARGS + ) + for arg_value in re.findall(arg_re, arguments_string): + if arg_value.split('=', 1)[0] not in valid_args: + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, + ) + logger.warning( + f"Invalid argument '{arg_value}' in" + f" '{directive}' directive at {location}. Ignoring...", + ) + def parse_filename_argument( match: re.Match[str], diff --git a/src/mkdocs_include_markdown_plugin/event.py b/src/mkdocs_include_markdown_plugin/event.py index 0798956..d52f9f4 100644 --- a/src/mkdocs_include_markdown_plugin/event.py +++ b/src/mkdocs_include_markdown_plugin/event.py @@ -3,7 +3,6 @@ from __future__ import annotations import html -import logging import os import re import textwrap @@ -23,8 +22,10 @@ parse_string_argument, resolve_file_paths_to_exclude, resolve_file_paths_to_include, + warn_invalid_directive_arguments, ) from mkdocs_include_markdown_plugin.files_watcher import FilesWatcher +from mkdocs_include_markdown_plugin.logger import logger if TYPE_CHECKING: @@ -48,46 +49,6 @@ class Settings: # noqa: D101 exclude: list[str] | None -# TODO: when Mkdocs < 1.5.0 support is dropped, use -# mkdocs.plugin.get_plugin_logger -logger = logging.getLogger('mkdocs.plugins.include_markdown') - - -def lineno_from_content_start(content: str, start: int) -> int: - """Return the line number of the first line of ``start`` in ``content``.""" - return content[:start].count('\n') + 1 - - -def safe_os_path_relpath(path: str, start: str) -> str: - """Return the relative path of a file from a start directory. - - Safe version of `os.path.relpath` that catches `ValueError` exceptions - on Windows and returns the original path in case of error. - On Windows, `ValueError` is raised when `path` and `start` are on - different drives. - """ - if os.name != 'nt': # pragma: nt no cover - return os.path.relpath(path, start) - try: # pragma: nt cover - return os.path.relpath(path, start) - except ValueError: # pragma: no cover - return path - - -def file_lineno_message( - page_src_path: str | None, - docs_dir: str, - lineno: int, -) -> str: - """Return a message with the file path and line number.""" - if page_src_path is None: # pragma: no cover - return f'generated page content (line {lineno})' - return ( - f'{safe_os_path_relpath(page_src_path, docs_dir)}' - f':{lineno}' - ) - - def get_file_content( # noqa: PLR0913, PLR0915 markdown: str, # Generated pages return `None` for `file.abs_src_path` because @@ -123,42 +84,48 @@ def found_include_tag( # noqa: PLR0912, PLR0915 match: re.Match[str], ) -> str: directive_match_start = match.start() + directive_lineno = process.lineno_from_content_start( + markdown, + directive_match_start, + ) includer_indent = match['_includer_indent'] filename, raw_filename = parse_filename_argument(match) if filename is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Found no path passed including with 'include'" - ' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) arguments_string = match['arguments'] + warn_invalid_directive_arguments( + arguments_string, + directive_lineno, + 'include', + page_src_path, + docs_dir, + ) + 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) if exclude_string is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'exclude' argument in 'include'" - ' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) for path in resolve_file_paths_to_exclude( - exclude_string, - page_src_path, - docs_dir, + exclude_string, page_src_path, docs_dir, ): if path not in ignore_paths: ignore_paths.append(path) @@ -171,13 +138,11 @@ def found_include_tag( # noqa: PLR0912, PLR0915 ) if not file_paths_to_include: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( - f"No files found including '{raw_filename}' at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f"No files found including '{raw_filename}' at {location}", ) if files_watcher is not None and not is_url: @@ -190,14 +155,12 @@ def found_include_tag( # noqa: PLR0912, PLR0915 arguments_string, ) if invalid_bool_args: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( f"Invalid value for '{invalid_bool_args[0]}' argument of" - " 'include' directive at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}.' + f" 'include' directive at {location}." f' Possible values are true or false.', ) @@ -205,13 +168,12 @@ def found_include_tag( # noqa: PLR0912, PLR0915 if start_match: start = parse_string_argument(start_match) if start is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'start' argument in 'include' directive at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' {location}', ) else: start = defaults['start'] @@ -220,13 +182,12 @@ def found_include_tag( # noqa: PLR0912, PLR0915 if end_match: end = parse_string_argument(end_match) if end is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'end' argument in 'include' directive at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' {location}', ) else: end = defaults['end'] @@ -235,14 +196,12 @@ def found_include_tag( # noqa: PLR0912, PLR0915 if encoding_match: encoding = parse_string_argument(encoding_match) if encoding is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'encoding' argument in 'include'" - ' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) else: encoding = defaults['encoding'] @@ -308,25 +267,18 @@ def found_include_tag( # noqa: PLR0912, PLR0915 if expected_but_any_found[i]: delimiter_value = locals()[delimiter_name] readable_files_to_include = ', '.join([ - safe_os_path_relpath(fpath, docs_dir) + process.safe_os_path_relpath(fpath, docs_dir) for fpath in file_paths_to_include ]) plural_suffix = 's' if len(file_paths_to_include) > 1 else '' - lineno = lineno_from_content_start( - markdown, - directive_match_start, - ) - file_lineno = file_lineno_message( - page_src_path, docs_dir, lineno, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) logger.warning( - ( - f"Delimiter {delimiter_name} '{delimiter_value}'" - " of 'include' directive at" - f' {file_lineno}' - f' not detected in the file{plural_suffix}' - f' {readable_files_to_include}' - ), + f"Delimiter {delimiter_name} '{delimiter_value}'" + f" of 'include' directive at {location}" + f' not detected in the file{plural_suffix}' + f' {readable_files_to_include}', ) return text_to_include @@ -335,42 +287,48 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 match: re.Match[str], ) -> str: directive_match_start = match.start() + directive_lineno = process.lineno_from_content_start( + markdown, + directive_match_start, + ) includer_indent = match['_includer_indent'] empty_includer_indent = ' ' * len(includer_indent) filename, raw_filename = parse_filename_argument(match) if filename is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Found no path passed including with 'include-markdown'" - f' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) arguments_string = match['arguments'] + warn_invalid_directive_arguments( + arguments_string, + directive_lineno, + 'include-markdown', + page_src_path, + docs_dir, + ) + 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) if exclude_string is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'exclude' argument in 'include-markdown'" - f' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) for path in resolve_file_paths_to_exclude( - exclude_string, - page_src_path, - docs_dir, + exclude_string, page_src_path, docs_dir, ): if path not in ignore_paths: ignore_paths.append(path) @@ -383,13 +341,11 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 ) if not file_paths_to_include: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( - f"No files found including '{raw_filename}' at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f"No files found including '{raw_filename}' at {location}", ) if files_watcher is not None and not is_url: @@ -405,15 +361,13 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 arguments_string, ) if invalid_bool_args: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( f"Invalid value for '{invalid_bool_args[0]}' argument of" " 'include-markdown' directive at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}.' - f' Possible values are true or false.', + f' {location}. Possible values are true or false.', ) # start and end arguments @@ -421,14 +375,12 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 if start_match: start = parse_string_argument(start_match) if start is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'start' argument in 'include-markdown'" - f' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) else: start = defaults['start'] @@ -437,14 +389,12 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 if end_match: end = parse_string_argument(end_match) if end is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'end' argument in 'include-markdown'" - f' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) else: end = defaults['end'] @@ -453,14 +403,12 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 if encoding_match: encoding = parse_string_argument(encoding_match) if encoding is None: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'encoding' argument in 'include-markdown'" - ' directive at' - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f' directive at {location}', ) else: encoding = defaults['encoding'] @@ -472,26 +420,22 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 if offset_match: offset_raw_value = offset_match[1] if offset_raw_value == '': - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( "Invalid empty 'heading-offset' argument in" - " 'include-markdown' directive at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f" 'include-markdown' directive at {location}", ) try: offset = int(offset_raw_value) except ValueError: - lineno = lineno_from_content_start( - markdown, - directive_match_start, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) raise PluginError( f"Invalid 'heading-offset' argument \"{offset_raw_value}\"" - " in 'include-markdown' directive at" - f' {file_lineno_message(page_src_path, docs_dir, lineno)}', + f" in 'include-markdown' directive at {location}", ) from None else: offset = defaults['heading-offset'] @@ -601,25 +545,18 @@ def found_include_markdown_tag( # noqa: PLR0912, PLR0915 if expected_but_any_found[i]: delimiter_value = locals()[delimiter_name] readable_files_to_include = ', '.join([ - safe_os_path_relpath(fpath, docs_dir) + process.safe_os_path_relpath(fpath, docs_dir) for fpath in file_paths_to_include ]) plural_suffix = 's' if len(file_paths_to_include) > 1 else '' - lineno = lineno_from_content_start( - markdown, - directive_match_start, - ) - file_lineno = file_lineno_message( - page_src_path, docs_dir, lineno, + location = process.file_lineno_message( + page_src_path, docs_dir, directive_lineno, ) logger.warning( - ( - f"Delimiter {delimiter_name} '{delimiter_value}' of" - " 'include-markdown' directive at" - f' {file_lineno}' - f' not detected in the file{plural_suffix}' - f' {readable_files_to_include}' - ), + f"Delimiter {delimiter_name} '{delimiter_value}' of" + f" 'include-markdown' directive at {location}" + f' not detected in the file{plural_suffix}' + f' {readable_files_to_include}', ) return text_to_include diff --git a/src/mkdocs_include_markdown_plugin/logger.py b/src/mkdocs_include_markdown_plugin/logger.py new file mode 100644 index 0000000..3af5241 --- /dev/null +++ b/src/mkdocs_include_markdown_plugin/logger.py @@ -0,0 +1,10 @@ +"""Mkdocs plugin logger.""" + +from __future__ import annotations + +import logging + + +# TODO: when Mkdocs < 1.5.0 support is dropped, use +# mkdocs.plugin.get_plugin_logger +logger = logging.getLogger('mkdocs.plugins.include_markdown') diff --git a/src/mkdocs_include_markdown_plugin/process.py b/src/mkdocs_include_markdown_plugin/process.py index d5fd066..8bd988e 100644 --- a/src/mkdocs_include_markdown_plugin/process.py +++ b/src/mkdocs_include_markdown_plugin/process.py @@ -452,3 +452,38 @@ def read_url(url: str, http_cache: Cache | None) -> Any: if http_cache is not None: http_cache.set_(url, content) return content + + +def safe_os_path_relpath(path: str, start: str) -> str: + """Return the relative path of a file from a start directory. + + Safe version of `os.path.relpath` that catches `ValueError` exceptions + on Windows and returns the original path in case of error. + On Windows, `ValueError` is raised when `path` and `start` are on + different drives. + """ + if os.name != 'nt': # pragma: nt no cover + return os.path.relpath(path, start) + try: # pragma: nt cover + return os.path.relpath(path, start) + except ValueError: # pragma: no cover + return path + + +def file_lineno_message( + page_src_path: str | None, + docs_dir: str, + lineno: int, +) -> str: + """Return a message with the file path and line number.""" + if page_src_path is None: # pragma: no cover + return f'generated page content (line {lineno})' + return ( + f'{safe_os_path_relpath(page_src_path, docs_dir)}' + f':{lineno}' + ) + + +def lineno_from_content_start(content: str, start: int) -> int: + """Return the line number of the first line of ``start`` in ``content``.""" + return content[:start].count('\n') + 1 diff --git a/tests/test_unit/test_arguments.py b/tests/test_unit/test_arguments.py index 5ac3e59..2d0f7b3 100644 --- a/tests/test_unit/test_arguments.py +++ b/tests/test_unit/test_arguments.py @@ -75,20 +75,25 @@ def test_start_end_mixed_quotes(directive, page, caplog, tmp_path, plugin): More content that should be ignored ''') - result = on_page_markdown( - f'''{{% + includer_file_content = f'''{{% {directive} "{page_to_include_filepath}" comments=false start='' end="" -%}}''', +%}}''' + if directive == 'include': + includer_file_content = includer_file_content.replace( + 'comments=false', '', + ) + result = on_page_markdown( + includer_file_content, page(tmp_path / 'includer.md'), tmp_path, plugin, ) assert result == '\nContent to include\n' - assert len(caplog.records) == 0 + assert caplog.records == [] @pytest.mark.parametrize('argument', ('start', 'end')) @@ -110,14 +115,19 @@ def test_invalid_start_end_arguments( ''' page_to_include_filepath.write_text(included_content) - with pytest.raises(PluginError) as exc: - on_page_markdown( - f''' + includer_file_content = f''' {{% {directive} "{page_to_include_filepath}" comments=false {argument}='' -%}}''', +%}}''' + if directive == 'include': + includer_file_content = includer_file_content.replace( + 'comments=false', '', + ) + with pytest.raises(PluginError) as exc: + on_page_markdown( + includer_file_content, page(tmp_path / 'includer.md'), tmp_path, plugin, @@ -132,7 +142,9 @@ def test_invalid_start_end_arguments( @unix_only @parametrize_directives -def test_exclude_double_quote_escapes(directive, page, tmp_path, plugin): +def test_exclude_double_quote_escapes( + directive, page, tmp_path, plugin, caplog, +): drectory_to_include = tmp_path / 'exclude_double_quote_escapes' drectory_to_include.mkdir() @@ -146,17 +158,23 @@ def test_exclude_double_quote_escapes(directive, page, tmp_path, plugin): ).replace('"', '\\"') includer_glob = os.path.join(str(drectory_to_include), '*.md') - result = on_page_markdown( - f'''{{% + includer_file_content = f'''{{% {directive} "{includer_glob}" comments=false exclude="{page_to_exclude_escaped_filepath}" -%}}''', +%}}''' + if directive == 'include': + includer_file_content = includer_file_content.replace( + 'comments=false', '', + ) + result = on_page_markdown( + includer_file_content, page(tmp_path / 'includer.md'), tmp_path, plugin, ) assert result == 'Content that should be included\n' + assert caplog.records == [] @unix_only @@ -172,13 +190,20 @@ def test_invalid_exclude_argument(directive, page, tmp_path, caplog, plugin): page_to_exclude_filepath.write_text('Content that should be excluded\n') includer_glob = os.path.join(str(drectory_to_include), '*.md') - with pytest.raises(PluginError) as exc: - on_page_markdown( - f'''{{% + + includer_file_content = f'''{{% {directive} "{includer_glob}" comments=false exclude= -%}}''', +%}}''' + if directive == 'include': + includer_file_content = includer_file_content.replace( + 'comments=false', '', + ) + + with pytest.raises(PluginError) as exc: + on_page_markdown( + includer_file_content, page(tmp_path / 'includer.md'), tmp_path, plugin, @@ -196,13 +221,19 @@ def test_empty_encoding_argument(directive, page, tmp_path, plugin, caplog): page_to_include_filepath = tmp_path / 'included.md' page_to_include_filepath.write_text('Content to include') - with pytest.raises(PluginError) as exc: - on_page_markdown( - f'''{{% + includer_file_content = f'''{{% {directive} "{page_to_include_filepath}" comments=false encoding= -%}}''', +%}}''' + if directive == 'include': + includer_file_content = includer_file_content.replace( + 'comments=false', '', + ) + + with pytest.raises(PluginError) as exc: + on_page_markdown( + includer_file_content, page(tmp_path / 'includer.md'), tmp_path, plugin, @@ -261,6 +292,34 @@ def test_invalid_heading_offset_arguments( assert str(exc.value) == exception_message +@parametrize_directives +def test_invalid_argument_name(directive, page, tmp_path, plugin, caplog): + page_to_include_filepath = tmp_path / 'included.md' + page_to_include_filepath.write_text('Content to include') + + includer_file_content = f'''{{% + {directive} "{page_to_include_filepath}" + comments=false + invalid-argument=true +%}}''' + if directive == 'include': + includer_file_content = includer_file_content.replace( + 'comments=false', '', + ) + assert on_page_markdown( + includer_file_content, + page(tmp_path / 'includer.md'), + tmp_path, + plugin, + ) == 'Content to include' + + assert len(caplog.records) == 1 + assert caplog.records[0].msg == ( + f"Invalid argument 'invalid-argument=true' in '{directive}'" + " directive at includer.md:1. Ignoring..." + ) + + class TestFilename: double_quoted_filenames = [ 'inc"luded.md', 'inc"lude"d.md', 'included.md"', '"included.md', diff --git a/tests/test_unit/test_exclude.py b/tests/test_unit/test_exclude.py index 414d933..9f58d47 100644 --- a/tests/test_unit/test_exclude.py +++ b/tests/test_unit/test_exclude.py @@ -87,6 +87,9 @@ def test_exclude( exclude='{exclude_prefix}{exclude}' comments=false %}}''' + if directive == 'include': + includer_file_content = includer_file_content.replace( + 'comments=false', '') for basename, file in files.items(): file.write_text(f'{basename}\n') diff --git a/tests/test_unit/test_glob_include.py b/tests/test_unit/test_glob_include.py index 10c878f..6406a00 100644 --- a/tests/test_unit/test_glob_include.py +++ b/tests/test_unit/test_glob_include.py @@ -137,6 +137,9 @@ def test_glob_include( caplog, tmp_path, ): + if directive == 'include': + includer_content = includer_content.replace('comments=false', '') + includer_file = tmp_path / 'includer.txt' included_01_file = tmp_path / 'included_01.txt' included_02_file = tmp_path / 'included_02.txt' diff --git a/tests/test_unit/test_include.py b/tests/test_unit/test_include.py index 9563947..2316e0b 100644 --- a/tests/test_unit/test_include.py +++ b/tests/test_unit/test_include.py @@ -184,7 +184,6 @@ {% include "{filepath}" start="" - comments=false %}''', '''Some text ''', @@ -207,7 +206,6 @@ {% include "{filepath}" end="" - comments=false %}''', ''' Some text diff --git a/tests/test_unit/test_nested_includes.py b/tests/test_unit/test_nested_includes.py index bd77777..9780989 100644 --- a/tests/test_unit/test_nested_includes.py +++ b/tests/test_unit/test_nested_includes.py @@ -232,7 +232,6 @@ {% include "{filepath}" - comments=false recursive=false %}''', '''# Header 2