mkdocs-include-markdown-plugin 7.0.0__tar.gz → 7.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (15) hide show
  1. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/.gitignore +1 -0
  2. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/PKG-INFO +2 -3
  3. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/pyproject.toml +1 -1
  4. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/cache.py +6 -8
  5. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/directive.py +41 -33
  6. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/event.py +3 -3
  7. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/plugin.py +1 -3
  8. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/process.py +18 -22
  9. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/LICENSE +0 -0
  10. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/README.md +0 -0
  11. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/__init__.py +0 -0
  12. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/config.py +0 -0
  13. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/files_watcher.py +0 -0
  14. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/logger.py +0 -0
  15. {mkdocs_include_markdown_plugin-7.0.0 → mkdocs_include_markdown_plugin-7.0.1}/src/mkdocs_include_markdown_plugin/py.typed +0 -0
@@ -17,5 +17,6 @@ venv*/
17
17
  .mypy_cache/
18
18
  *.so
19
19
  .prettier-cache
20
+ /*.html
20
21
 
21
22
  site/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mkdocs-include-markdown-plugin
3
- Version: 7.0.0
3
+ Version: 7.0.1
4
4
  Summary: Mkdocs Markdown includer plugin.
5
5
  Project-URL: Source, https://github.com/mondeja/mkdocs-include-markdown-plugin
6
6
  Project-URL: Documentation, https://github.com/mondeja/mkdocs-include-markdown-plugin#documentation
@@ -9,8 +9,7 @@ Project-URL: Changelog, https://github.com/mondeja/mkdocs-include-markdown-plugi
9
9
  Author: Joe Rickerby
10
10
  Author-email: Álvaro Mondéjar Rubio <mondejar1994@gmail.com>
11
11
  Maintainer-email: Álvaro Mondéjar Rubio <mondejar1994@gmail.com>
12
- License-Expression: Apache-2.0
13
- License-File: LICENSE
12
+ License: Apache-2.0
14
13
  Keywords: includer,markdown,mkdocs,plugin
15
14
  Classifier: Development Status :: 5 - Production/Stable
16
15
  Classifier: Environment :: Console
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mkdocs-include-markdown-plugin"
3
- version = "7.0.0"
3
+ version = "7.0.1"
4
4
  description = "Mkdocs Markdown includer plugin."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -2,7 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import base64
6
5
  import hashlib
7
6
  import os
8
7
  import time
@@ -29,15 +28,13 @@ class Cache:
29
28
 
30
29
  def get_creation_time_from_fpath(self, fpath: str) -> int:
31
30
  """Get creation time of an entry in the cache given its path."""
32
- with open(fpath, encoding='utf-8') as f:
31
+ with open(fpath, 'rb') as f:
33
32
  return int(f.readline())
34
33
 
35
34
  @classmethod
36
35
  def generate_unique_key_from_url(cls, url: str) -> str:
37
36
  """Generate a unique key from an URL."""
38
- return base64.urlsafe_b64encode(
39
- hashlib.sha3_512(url.encode()).digest(),
40
- ).decode('utf-8')
37
+ return hashlib.blake2b(url.encode(), digest_size=16).digest().hex()
41
38
 
42
39
  def read_file(self, fpath: str, encoding: str = 'utf-8') -> str: # noqa: D102
43
40
  with open(fpath, encoding=encoding) as f:
@@ -56,9 +53,10 @@ class Cache:
56
53
  def set_(self, url: str, value: str, encoding: str = 'utf-8') -> None: # noqa: D102
57
54
  key = self.generate_unique_key_from_url(url)
58
55
  fpath = os.path.join(self.cache_dir, key)
59
- with open(fpath, 'w', encoding=encoding) as f:
60
- f.write(f'{int(time.time())}\n')
61
- f.write(value)
56
+ with open(fpath, 'wb') as fp:
57
+ now = f'{int(time.time())}\n'
58
+ fp.write(now.encode(encoding))
59
+ fp.write(value.encode(encoding))
62
60
 
63
61
  def clean(self) -> None:
64
62
  """Clean expired entries from the cache."""
@@ -21,7 +21,7 @@ class DirectiveBoolArgument: # noqa: D101
21
21
  regex: re.Pattern[str]
22
22
 
23
23
 
24
- if TYPE_CHECKING:
24
+ if TYPE_CHECKING: # pragma: no cover
25
25
  from typing import Literal, TypedDict
26
26
 
27
27
  DirectiveBoolArgumentsDict = dict[str, DirectiveBoolArgument]
@@ -112,6 +112,10 @@ INCLUDE_DIRECTIVE_ARGS = {
112
112
 
113
113
  INCLUDE_MARKDOWN_DIRECTIVE_ARGS = set(ARGUMENT_REGEXES)
114
114
 
115
+ WARN_INVALID_DIRECTIVE_ARGS_REGEX = re.compile(
116
+ rf'[\w-]*=[{RE_ESCAPED_PUNCTUATION}\w]*',
117
+ )
118
+
115
119
 
116
120
  def warn_invalid_directive_arguments(
117
121
  arguments_string: str,
@@ -121,12 +125,14 @@ def warn_invalid_directive_arguments(
121
125
  docs_dir: str,
122
126
  ) -> None:
123
127
  """Warns about the invalid arguments passed to a directive."""
124
- arg_re = re.compile(rf'[\w-]*=[{RE_ESCAPED_PUNCTUATION}\w]*')
125
128
  valid_args = (
126
129
  INCLUDE_DIRECTIVE_ARGS if directive == 'include'
127
130
  else INCLUDE_MARKDOWN_DIRECTIVE_ARGS
128
131
  )
129
- for arg_value in re.findall(arg_re, arguments_string):
132
+ for arg_value in re.findall(
133
+ WARN_INVALID_DIRECTIVE_ARGS_REGEX,
134
+ arguments_string,
135
+ ):
130
136
  if arg_value.split('=', 1)[0] not in valid_args:
131
137
  location = process.file_lineno_message(
132
138
  page_src_path, docs_dir, directive_lineno,
@@ -174,9 +180,9 @@ def create_include_tag(
174
180
  INCLUDE_TAG_RE by the effective tag.
175
181
  """
176
182
  return re.compile(
177
- INCLUDE_TAG_RE.replace(' include', f' {tag}').replace(
178
- '$OPENING_TAG', re.escape(opening_tag),
179
- ).replace('$CLOSING_TAG', re.escape(closing_tag)),
183
+ INCLUDE_TAG_RE.replace(' include', f' {tag}', 1).replace(
184
+ '$OPENING_TAG', re.escape(opening_tag), 1,
185
+ ).replace('$CLOSING_TAG', re.escape(closing_tag), 1),
180
186
  flags=re.VERBOSE | re.DOTALL,
181
187
  )
182
188
 
@@ -209,7 +215,7 @@ def parse_bool_options(
209
215
  return bool_options, invalid_args
210
216
 
211
217
 
212
- def resolve_file_paths_to_include(
218
+ def resolve_file_paths_to_include( # noqa: PLR0912
213
219
  include_string: str,
214
220
  includer_page_src_path: str | None,
215
221
  docs_dir: str,
@@ -229,13 +235,11 @@ def resolve_file_paths_to_include(
229
235
  return process.filter_paths(
230
236
  [fpath], ignore_paths,
231
237
  ), False
238
+
232
239
  return process.filter_paths(
233
- glob.iglob(
234
- os.path.normpath(include_string),
235
- flags=GLOB_FLAGS,
236
- ),
237
- ignore_paths,
238
- ), False
240
+ [include_string] if os.path.isfile(include_string)
241
+ else glob.iglob(include_string, flags=GLOB_FLAGS),
242
+ ignore_paths), False
239
243
 
240
244
  if process.is_relative_path(include_string):
241
245
  if includer_page_src_path is None: # pragma: no cover
@@ -247,29 +251,33 @@ def resolve_file_paths_to_include(
247
251
  root_dir = os.path.abspath(
248
252
  os.path.dirname(includer_page_src_path),
249
253
  )
250
- return process.filter_paths(
251
- (
252
- os.path.normpath(os.path.join(root_dir, fp))
253
- for fp in glob.iglob(
254
- include_string,
255
- flags=GLOB_FLAGS,
256
- root_dir=root_dir,
257
- )
258
- ), ignore_paths,
259
- ), False
260
-
261
- # relative to docs_dir
262
- return process.filter_paths(
263
- (
264
- os.path.normpath(os.path.join(docs_dir, fp))
254
+ paths = []
255
+ include_path = os.path.join(root_dir, include_string)
256
+ if os.path.isfile(include_path):
257
+ paths.append(include_path)
258
+ else:
265
259
  for fp in glob.iglob(
266
260
  include_string,
267
261
  flags=GLOB_FLAGS,
268
- root_dir=docs_dir,
269
- )
270
- ),
271
- ignore_paths,
272
- ), False
262
+ root_dir=root_dir,
263
+ ):
264
+ paths.append(os.path.join(root_dir, fp))
265
+ return process.filter_paths(paths, ignore_paths), False
266
+
267
+ # relative to docs_dir
268
+ paths = []
269
+ root_dir = docs_dir
270
+ include_path = os.path.join(root_dir, include_string)
271
+ if os.path.isfile(include_path):
272
+ paths.append(include_path)
273
+ else:
274
+ for fp in glob.iglob(
275
+ include_string,
276
+ flags=GLOB_FLAGS,
277
+ root_dir=root_dir,
278
+ ):
279
+ paths.append(os.path.join(root_dir, fp))
280
+ return process.filter_paths(paths, ignore_paths), False
273
281
 
274
282
 
275
283
  def resolve_file_paths_to_exclude(
@@ -28,7 +28,7 @@ from mkdocs_include_markdown_plugin.files_watcher import FilesWatcher
28
28
  from mkdocs_include_markdown_plugin.logger import logger
29
29
 
30
30
 
31
- if TYPE_CHECKING:
31
+ if TYPE_CHECKING: # pragma: no cover
32
32
  from typing import Literal, TypedDict
33
33
 
34
34
  from mkdocs.structure.pages import Page
@@ -630,8 +630,8 @@ def on_page_markdown(
630
630
  page.file.abs_src_path,
631
631
  docs_dir,
632
632
  {
633
- 'include': plugin._include_tag,
634
- 'include-markdown': plugin._include_markdown_tag,
633
+ 'include': plugin._include_tag(),
634
+ 'include-markdown': plugin._include_markdown_tag(),
635
635
  },
636
636
  {
637
637
  'encoding': config.encoding,
@@ -11,7 +11,7 @@ from mkdocs.livereload import LiveReloadServer
11
11
  from mkdocs.plugins import BasePlugin, event_priority
12
12
 
13
13
 
14
- if TYPE_CHECKING:
14
+ if TYPE_CHECKING: # pragma: no cover
15
15
  import re
16
16
 
17
17
  from mkdocs.config.defaults import MkDocsConfig
@@ -46,14 +46,12 @@ class IncludeMarkdownPlugin(BasePlugin[PluginConfig]):
46
46
 
47
47
  return config
48
48
 
49
- @cached_property
50
49
  def _include_tag(self) -> re.Pattern[str]:
51
50
  return create_include_tag(
52
51
  self.config.opening_tag,
53
52
  self.config.closing_tag,
54
53
  )
55
54
 
56
- @cached_property
57
55
  def _include_markdown_tag(self) -> re.Pattern[str]:
58
56
  return create_include_tag(
59
57
  self.config.opening_tag,
@@ -12,7 +12,7 @@ from urllib.parse import urlparse, urlunparse
12
12
  from urllib.request import Request, urlopen
13
13
 
14
14
 
15
- if TYPE_CHECKING:
15
+ if TYPE_CHECKING: # pragma: no cover
16
16
  from typing import Any
17
17
 
18
18
  from mkdocs_include_markdown_plugin.cache import Cache
@@ -51,9 +51,9 @@ MARKDOWN_LINK_REGEX = re.compile( # noqa: DUO138
51
51
  )
52
52
  \]
53
53
  \( # literal paren
54
- [ \t]*
54
+ \s*
55
55
  <?(.*?)>? # href = $3
56
- [ \t]*
56
+ \s*
57
57
  ( # $4
58
58
  (['"]) # quote char = $5
59
59
  (.*?) # Title = $6
@@ -145,10 +145,7 @@ def transform_p_by_p_skipping_codeblocks( # noqa: PLR0912, PLR0915
145
145
  for line in io.StringIO(markdown):
146
146
  if not _current_fcodeblock_delimiter:
147
147
  lstripped_line = line.lstrip()
148
- if (
149
- lstripped_line.startswith('```')
150
- or lstripped_line.startswith('~~~')
151
- ):
148
+ if lstripped_line.startswith(('```', '~~~')):
152
149
  _current_fcodeblock_delimiter = lstripped_line[:3]
153
150
  process_current_paragraph()
154
151
  current_paragraph = ''
@@ -226,10 +223,7 @@ def transform_line_by_line_skipping_codeblocks(
226
223
  for line in io.StringIO(markdown):
227
224
  if not _current_fcodeblock_delimiter:
228
225
  lstripped_line = line.lstrip()
229
- if (
230
- lstripped_line.startswith('```')
231
- or lstripped_line.startswith('~~~')
232
- ):
226
+ if lstripped_line.startswith(('```', '~~~')):
233
227
  _current_fcodeblock_delimiter = lstripped_line[:3]
234
228
  else:
235
229
  line = func(line) # noqa: PLW2901
@@ -255,25 +249,23 @@ def rewrite_relative_urls(
255
249
  scheme, netloc, path, params, query, fragment = urlparse(url)
256
250
 
257
251
  # absolute or mail
258
- if path.startswith('/') or scheme == 'mailto':
252
+ if is_relative_path(url) or path.startswith('/') or scheme == 'mailto':
259
253
  return url
260
254
 
261
- trailing_slash = path.endswith('/')
262
-
263
- path = os.path.relpath(
255
+ new_path = os.path.relpath(
264
256
  os.path.join(os.path.dirname(source_path), path),
265
257
  os.path.dirname(destination_path),
266
258
  )
267
259
 
268
260
  # ensure forward slashes are used, on Windows
269
- path = path.replace('\\', '/').replace('//', '/')
261
+ new_path = new_path.replace('\\', '/').replace('//', '/')
270
262
 
271
- if trailing_slash:
263
+ if path.endswith('/'):
272
264
  # the above operation removes a trailing slash. Add it back if it
273
265
  # was present in the input
274
- path = path + '/'
266
+ new_path = new_path + '/'
275
267
 
276
- return urlunparse((scheme, netloc, path, params, query, fragment))
268
+ return urlunparse((scheme, netloc, new_path, params, query, fragment))
277
269
 
278
270
  def found_href(m: re.Match[str], url_group_index: int = -1) -> str:
279
271
  match_start, match_end = m.span(0)
@@ -400,7 +392,7 @@ def _transform_positive_offset_func_factory(
400
392
 
401
393
  def increase_headings_offset(markdown: str, offset: int = 0) -> str:
402
394
  """Increases the headings depth of a snippet of Makdown content."""
403
- if not offset:
395
+ if not offset: # pragma: no cover
404
396
  return markdown
405
397
  return transform_line_by_line_skipping_codeblocks(
406
398
  markdown,
@@ -444,7 +436,9 @@ def filter_paths(
444
436
  continue
445
437
 
446
438
  # ignore by dirpath (relative or absolute)
447
- if (os.sep).join(filepath.split(os.sep)[:-1]) in ignore_paths:
439
+ fp_split = filepath.split(os.sep)
440
+ fp_split.pop()
441
+ if (os.sep).join(fp_split) in ignore_paths:
448
442
  continue
449
443
 
450
444
  # ignore if is a directory
@@ -456,6 +450,8 @@ def filter_paths(
456
450
 
457
451
  def is_url(string: str) -> bool:
458
452
  """Determine if a string is an URL."""
453
+ if ':' not in string: # fast path
454
+ return False
459
455
  try:
460
456
  result = urlparse(string)
461
457
  return all([result.scheme, result.netloc])
@@ -470,7 +466,7 @@ def is_relative_path(string: str) -> bool:
470
466
 
471
467
  def is_absolute_path(string: str) -> bool:
472
468
  """Check if a string looks like an absolute path."""
473
- return os.path.isabs(string) or string.startswith((os.sep, '/'))
469
+ return string.startswith((os.sep, '/'))
474
470
 
475
471
 
476
472
  def read_file(file_path: str, encoding: str) -> str: