Document the !relative tag

This commit is contained in:
Oleh Prypin
2023-06-25 23:08:42 +02:00
parent 7d8483904a
commit 99a9a90553
3 changed files with 86 additions and 20 deletions

View File

@@ -110,7 +110,7 @@ class MyPlugin(mkdocs.plugins.BasePlugin):
> from mkdocs.config import base, config_options as c
>
> class _ValidationOptions(base.Config):
> enable = c.Type(bool, default=True)
> enabled = c.Type(bool, default=True)
> verbose = c.Type(bool, default=False)
> skip_checks = c.ListOfItems(c.Choice(('foo', 'bar', 'baz')), default=[])
>
@@ -130,7 +130,7 @@ class MyPlugin(mkdocs.plugins.BasePlugin):
> my_plugin:
> definition_file: configs/test.ini # relative to mkdocs.yml
> validation:
> enable: !ENV [CI, false]
> enabled: !ENV [CI, false]
> verbose: true
> skip_checks:
> - foo

View File

@@ -618,7 +618,7 @@ For example, to enable permalinks in the (included) `toc` extension, use:
```yaml
markdown_extensions:
- toc:
permalink: True
permalink: true
```
Note that a colon (`:`) must follow the extension name (`toc`) and then on a new
@@ -629,7 +629,7 @@ defined on a separate line:
```yaml
markdown_extensions:
- toc:
permalink: True
permalink: true
separator: "_"
```
@@ -641,10 +641,14 @@ for that extension:
markdown_extensions:
- smarty
- toc:
permalink: True
permalink: true
- sane_lists
```
> NOTE: **Dynamic config values.**
>
> To dynamically configure the extensions, you can get the config values from [environment variables](#environment-variables) or [obtain paths](#paths-relative-to-the-current-file-or-site) of the currently rendered Markdown file or the overall MkDocs site.
In the above examples, each extension is a list item (starts with a `-`). As an
alternative, key/value pairs can be used instead. However, in that case an empty
value must be provided for extensions for which no options are defined.
@@ -654,14 +658,14 @@ Therefore, the last example above could also be defined as follows:
markdown_extensions:
smarty: {}
toc:
permalink: True
permalink: true
sane_lists: {}
```
This alternative syntax is required if you intend to override some options via
[inheritance].
> NOTE: **See Also:**
> NOTE: **More extensions.**
>
> The Python-Markdown documentation provides a [list of extensions][exts]
> which are available out-of-the-box. For a list of configuration options
@@ -896,7 +900,9 @@ plugins:
**default**: `full`
## Environment Variables
## Special YAML tags
### Environment variables
In most cases, the value of a configuration option is set directly in the
configuration file. However, as an option, the value of a configuration option
@@ -933,6 +939,41 @@ cannot be defined within a single environment variable.
For more details, see the [pyyaml_env_tag](https://github.com/waylan/pyyaml-env-tag)
project.
### Paths relative to the current file or site
NEW: **New in version 1.5.**
Some Markdown extensions can benefit from knowing the path of the Markdown file that's currently being processed, or just the root path of the current site. For that, the special tag `!relative` can be used in most contexts within the config file, though the only known usecases are within [`markdown_extensions`](#markdown_extensions).
Examples of the possible values are:
```yaml
- !relative # Relative to the directory of the current Markdown file
- !relative $docs_dir # Path of the docs_dir
- !relative $config_dir # Path of the directory that contains the main mkdocs.yml
- !relative $config_dir/some/child/dir # Some subdirectory of the root config directory
```
(Here, `$docs_dir` and `$config_dir` are currently the *only* special prefixes that are recognized.)
Example:
```yaml
markdown_extensions:
- pymdownx.snippets:
base_path: !relative # Relative to the current Markdown file
```
This allows the [pymdownx.snippets] extension to include files relative to the current Markdown file, which without this tag it would have no way of knowing.
> NOTE: Even for the default case, any extension's base path is technically the *current working directory* although the assumption is that it's the *directory of mkdocs.yml*. So even if you don't want the paths to be relative, to improve the default behavior, always prefer to use this idiom:
>
> ```yaml
> markdown_extensions:
> - pymdownx.snippets:
> base_path: !relative $config_dir # Relative to the root directory with mkdocs.yml
> ```
## Configuration Inheritance
Generally, a single file would hold the entire configuration for a site.
@@ -1077,3 +1118,4 @@ echo '{INHERIT: mkdocs.yml, site_name: "Renamed site"}' | mkdocs build -f -
[markdown_extensions]: #markdown_extensions
[nav]: #nav
[inheritance]: #configuration-inheritance
[pymdownx.snippets]: https://facelessuser.github.io/pymdown-extensions/extensions/snippets/

View File

@@ -24,23 +24,19 @@ def _construct_dir_placeholder(
) -> _DirPlaceholder:
loader.construct_scalar(node)
value = (node and node.value) or ''
prefix, _, subvalue = value.partition('/')
value: str = (node and node.value) or ''
prefix, _, suffix = value.partition('/')
if prefix.startswith('$'):
if prefix == '$config_dir':
return _ConfigDirPlaceholder(config, subvalue)
return ConfigDirPlaceholder(config, suffix)
elif prefix == '$docs_dir':
return _DocsDirPlaceholder(config, subvalue)
return DocsDirPlaceholder(config, suffix)
else:
raise exceptions.ConfigurationError(
f"Unknown prefix {prefix!r} in {node.tag} {node.value!r}"
)
else:
if value:
raise exceptions.ConfigurationError(
f"{node.tag!r} tag does not expect any value; received {node.value!r}"
)
return _RelativeDirPlaceholder(config)
return RelativeDirPlaceholder(config, value)
class _DirPlaceholder(os.PathLike):
@@ -52,23 +48,51 @@ class _DirPlaceholder(os.PathLike):
raise NotImplementedError
def __fspath__(self) -> str:
"""Can be used as a path."""
return os.path.join(self.value(), self.suffix)
def __str__(self) -> str:
"""Can be converted to a string to obtain the current class."""
return self.__fspath__()
class _ConfigDirPlaceholder(_DirPlaceholder):
class ConfigDirPlaceholder(_DirPlaceholder):
"""A placeholder object that gets resolved to the directory of the config file when used as a path.
The suffix can be an additional sub-path that is always appended to this path.
This is the implementation of the `!relative $config_dir/suffix` tag, but can also be passed programmatically.
"""
def value(self) -> str:
return os.path.dirname(self.config.config_file_path)
class _DocsDirPlaceholder(_DirPlaceholder):
class DocsDirPlaceholder(_DirPlaceholder):
"""A placeholder object that gets resolved to the docs dir when used as a path.
The suffix can be an additional sub-path that is always appended to this path.
This is the implementation of the `!relative $docs_dir/suffix` tag, but can also be passed programmatically.
"""
def value(self) -> str:
return self.config.docs_dir
class _RelativeDirPlaceholder(_DirPlaceholder):
class RelativeDirPlaceholder(_DirPlaceholder):
"""A placeholder object that gets resolved to the directory of the Markdown file currently being rendered.
This is the implementation of the `!relative` tag, but can also be passed programmatically.
"""
def __init__(self, config: MkDocsConfig, suffix: str = ''):
if suffix:
raise exceptions.ConfigurationError(
f"'!relative' tag does not expect any value; received {suffix!r}"
)
super().__init__(config, suffix)
def value(self) -> str:
if self.config._current_page is None:
raise exceptions.ConfigurationError(