plugins.py
Set of methods to manage mkdocs configuration dynamically.
Set of methods for mkdocs-macros-plugin Set of which :
- Define macros usable in jinja template
- Update
env.conf, i.e. mkdocs configuration based on variables files - Dynamically update
envdictionary andnaventries to support subrepo either internal subrepo, using mkdocs-monorepo-plugin, or external subrepo by usingonline_urlof such subrepo.
This script allow to make content of mkdocs.yml to be templated, i.e. using
the same mkdocs.yml file for multiple repos and use variables files in
docs/_data/
Attributes
plugins.ERR_CLR
String coloring error output in red.
plugins.INFO_CLR
String coloring error output in green.
plugins.LOG
The logger facilty.
plugins.RESET_CLR
String reseting coloring output.
Functions
plugins.add_external_to_nav(env, nav, repo_dict, repo_parent, nav_parent)
Add external subrepo to nav key of mkdocs.yml.
This method recursively parse nav_parent arguments to know where to
include the external subrepo into nav key.
Once determined, add the subrepo as a entry to the nav key, with the
online_url key of the current subrepo defined with repo_dict in file
subrepo.yml in docs/_data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
nav |
Navigation dictionary (subpart of it if called recursively) |
required | |
repo_dict |
Repo dictionary from |
required | |
repo_parent |
List of keys storing parent keys of the current
|
required | |
nav_parent |
List of keys storing parents |
required |
Source code in _data/plugins.py
def add_external_to_nav(
env: dict, nav: dict, repo_dict: dict, repo_parent: list, nav_parent: list
) -> None:
"""Add external subrepo to `nav` key of mkdocs.yml.
This method recursively parse `nav_parent` arguments to know where to
include the external subrepo into `nav` key.
Once determined, add the subrepo as a entry to the `nav` key, with the
`online_url` key of the current subrepo defined with `repo_dict` in file
`subrepo.yml` in `docs/_data`.
Args:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
nav : Navigation dictionary (subpart of it if called recursively)
repo_dict : Repo dictionary from `subrepo.yml` file in `docs/_data/`
repo_parent : List of keys storing parent keys of the current
`repo_dict` from `subrepo.yml` file in `docs/_data`
nav_parent : List of keys storing parents `nav_entry` keys of the
current `repo_dict` from `subrepo.yml` file in `docs/_data`
"""
if nav_parent:
for i_nav in nav:
if nav_parent[0] in i_nav:
for i_key in i_nav:
add_external_to_nav(
env,
i_nav[i_key],
repo_dict,
repo_parent,
nav_parent[1:],
)
elif repo_dict["online_url"].startswith("/"):
nav.append(
{
repo_dict["nav_entry"]: repo_dict["online_url"].replace(
"/", "../", 1
)
}
)
else:
nav.append({repo_dict["nav_entry"]: repo_dict["online_url"]})
plugins.add_internal_to_nav(env, nav, repo_dict, repo_parent, nav_parent=None)
Add internal subrepo to nav key of mkdocs.yml for monorepo.
This method recursively parse nav_parent arguments to know where to
include the internal subrepo into nav key.
Once determined, add the subrepo as a entry to the nav key, with the
format required by
mkdocs-monorepo-plugin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
nav |
Navigation dictionary (subpart of it if called recursively) |
required | |
repo_dict |
Repo dictionary from |
required | |
repo_parent |
List of keys storing parent keys of the current
|
required | |
nav_parent |
List of keys storing parents |
None |
Source code in _data/plugins.py
def add_internal_to_nav(
env: dict,
nav: dict,
repo_dict: dict,
repo_parent: list,
nav_parent: list = None,
) -> None:
"""Add internal subrepo to `nav` key of mkdocs.yml for monorepo.
This method recursively parse `nav_parent` arguments to know where to
include the internal subrepo into `nav` key.
Once determined, add the subrepo as a entry to the `nav` key, with the
format required by
[mkdocs-monorepo-plugin](https://github.com/backstage/mkdocs-monorepo-plugin).
Args:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
nav : Navigation dictionary (subpart of it if called
recursively)
repo_dict : Repo dictionary from `subrepo.yml` file in `docs/_data/`
repo_parent : List of keys storing parent keys of the current
`repo_dict` from `subrepo.yml` file in `docs/_data`
nav_parent : List of keys storing parents `nav_entry` keys of the
current `repo_dict` from `subrepo.yml` file in `docs/_data`
"""
if nav_parent:
for i_nav in nav:
# "nav_entry" is a key of current parsed `nav`
if nav_parent[0] in i_nav:
for i_key in i_nav:
add_internal_to_nav(
env,
i_nav[i_key],
repo_dict,
repo_parent,
nav_parent[1:],
)
# "nav_entry" is a subkey of current parsed `nav`
elif nav_parent[0] in yaml.dump(i_nav):
for i_key in i_nav:
add_internal_to_nav(
env,
i_nav[i_key],
repo_dict,
repo_parent,
nav_parent[0:],
)
else:
mkdocs_path = env.project_dir
for i_parent in repo_parent:
mkdocs_path = os.path.join(mkdocs_path, i_parent)
mkdocs_path = os.path.join(mkdocs_path, repo_dict["name"])
if "subpath" in repo_dict:
mkdocs_path = os.path.join(mkdocs_path, repo_dict["subpath"])
mkdocs_path = os.path.join(mkdocs_path, "mkdocs.yml")
nav.append({repo_dict["nav_entry"]: f"!include {mkdocs_path}"})
plugins.add_nav_entry(nav, nav_parent=None)
Create missing entry into nav key of env.conf.
Recursively parse list nav_parent and create missing entry into key nav
of mkdocs.yml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nav |
Navigation dictionary (subpart of it if called recursively) |
required | |
nav_parent |
List of keys storing parents |
None |
Source code in _data/plugins.py
def add_nav_entry(nav: list, nav_parent: list = None) -> None:
"""Create missing entry into `nav` key of `env.conf`.
Recursively parse list `nav_parent` and create missing entry into key `nav`
of mkdocs.yml.
Args:
nav : Navigation dictionary (subpart of it if called recursively)
nav_parent : List of keys storing parents `nav_entry` keys
"""
entry = {}
for i_nav in nav:
if nav_parent[0] in i_nav:
entry = i_nav
if not entry:
entry = {nav_parent[0]: []}
nav.append(entry)
if len(nav_parent[1:]) == 0:
return
add_nav_entry(entry[nav_parent[0]], nav_parent[1:])
plugins.define_env(env)
Hook for mkdocs-macros-plugins defining variables, macros and filters.
This is the hook for defining variables, macros and filters
- variables: the dictionary that contains the environment variables
- macro: a decorator function, to declare a macro.
See https://mkdocs-macros-plugin.readthedocs.io/en/latest/
This hooks also start the initialization of the dynamic configuration of mkdocs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
Source code in _data/plugins.py
def define_env(env: dict) -> None:
# pylint: disable=C0301
# - C0301: Line to long
"""Hook for mkdocs-macros-plugins defining variables, macros and filters.
This is the hook for defining variables, macros and filters
- variables: the dictionary that contains the environment variables
- macro: a decorator function, to declare a macro.
See
[https://mkdocs-macros-plugin.readthedocs.io/en/latest/](https://mkdocs-macros-plugin.readthedocs.io/en/latest/)
This hooks also start the initialization of the dynamic configuration of
mkdocs.
Arguments:
env: Mkdocs macro plugin environment dictionary.
"""
load_var_file(env)
if "subrepo" in env.variables:
env.variables["internal_subdoc"] = False
env.variables.update(
update_subrepo(
env, env.variables["subrepo"], env.project_dir, False
)
)
set_config(env)
update_version(env)
@env.macro
# pylint: disable=W0612
# - W0612: Unused variable (unused-variable)
def subs(var: str) -> dict:
"""Return the content of the dictionary defined by var.
Arguments:
var: Key in env.variables to return.
Returns:
The value of `env.variables[var]` if it exists, else return None.
"""
if var in env.variables:
return env.variables[var]
return None
@env.macro
# pylint: disable=W0612
# - W0612: Unused variable (unused-variable)
def to_html(var: str) -> dict:
"""Convert the content of the markdown string into HTML.
Arguments:
var: Markdown string which need to be converted to HTML
Returns:
The content of the markdown converted to HTML
"""
return markdown.markdown(var)
plugins.get_repo_slug(env, git_repo)
Compute the slug of the git_repo and ensure repo dictionary is defined.
Compute the slug of the repo provided as git_repo based on the origin
remote. If no remo, then will use the folder name.
Then ensure the repo dictionary is defined in docs/_data/. If not, print
an error and exit.
Else, update value of env.variables["git"] and return the repo_slug.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
git_repo |
Repo |
Git python object of the current repo. |
required |
Returns:
| Type | Description |
|---|---|
str |
Posix path from |
Source code in _data/plugins.py
def get_repo_slug(env: dict, git_repo: git.Repo) -> str:
"""Compute the slug of the `git_repo` and ensure repo dictionary is defined.
Compute the slug of the repo provided as `git_repo` based on the origin
remote. If no remo, then will use the folder name.
Then ensure the repo dictionary is defined in `docs/_data/`. If not, print
an error and exit.
Else, update value of `env.variables["git"]` and return the `repo_slug`.
Arguments:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
git_repo: Git python object of the current repo.
Returns:
Posix path from `os.path` python library.
"""
if git_repo.remotes:
repo_slug = (
git_repo.remotes.origin.url.rsplit("/")[-1]
.split(".git")[0]
.replace(".", "_")
)
else:
repo_slug = os.path.basename(env.project_dir)
if repo_slug not in env.variables:
LOG.error(
"%s[macros] - Dictionary %s is not defined.%s",
ERR_CLR,
repo_slug,
RESET_CLR,
)
LOG.error(
"%s[macros] - Ensure you copy docs/_data/templates/repo.tpl.yaml "
"to docs/_data/%s.yaml.%s",
ERR_CLR,
repo_slug,
RESET_CLR,
)
LOG.error(
"%s[macros] - And you setup dictionary %s in docs/_data/%s.yaml.%s",
ERR_CLR,
repo_slug,
repo_slug,
RESET_CLR,
)
sys.exit(1)
env.variables["git"]["repo_slug"] = repo_slug
return repo_slug
plugins.load_var_file(env)
Load variables files in docs/_data/.
Load every yaml files in docs/_data/, if one of the file define the
current repo, then update keys logo and src_path for the current repo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required |
Source code in _data/plugins.py
def load_var_file(env: dict) -> None:
"""Load variables files in `docs/_data/`.
Load every yaml files in `docs/_data/`, if one of the file define the
current repo, then update keys `logo` and `src_path` for the current repo.
Arguments:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
"""
var_dir = os.path.join(env.project_dir, "docs", "_data")
for i_file in os.listdir(var_dir):
if i_file.endswith((".yml", ".yaml")):
data, data_type = load_yaml_file(var_dir, i_file)
for i_key in data:
if data_type == "repo":
update_logo_src_repo(env, data[i_key], i_key)
env.variables[i_key] = data[i_key]
plugins.load_yaml_file(path, filename)
Ensure a YAML file is valid again a schema and return its content.
Depending on the name of the YAML file, compare its content to a schema to validate its content. If content is not valid, an error will be raised. Otherwise, its content will be returned.
If filename is extra.yml or extra.yaml, load content of the file
unconditionnally.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path |
str |
Base path where YAML files are. |
required |
filename |
str |
Name of the YAML file to load. |
required |
Source code in _data/plugins.py
def load_yaml_file(path: str, filename: str) -> None:
"""Ensure a YAML file is valid again a schema and return its content.
Depending on the name of the YAML file, compare its content to a schema to
validate its content. If content is not valid, an error will be raised.
Otherwise, its content will be returned.
If filename is `extra.yml` or `extra.yaml`, load content of the file
unconditionnally.
Arguments:
path: Base path where YAML files are.
filename: Name of the YAML file to load.
"""
source_file = os.path.join(path, filename)
schema_file = os.path.join(path, "schema")
data_type = ""
if filename not in ("extra.yaml", "extra.yml"):
if filename in ("subrepo.yaml", "subrepo.yml"):
schema_file = os.path.join(schema_file, "subrepo.schema.yaml")
elif filename in ("vars.yaml", "vars.yml"):
schema_file = os.path.join(schema_file, "vars.schema.yaml")
elif filename not in ("extra.yaml", "extra.yml"):
schema_file = os.path.join(schema_file, "repo.schema.yaml")
data_type = "repo"
schema = yamlschema(source_file=source_file, schema_files=[schema_file])
schema.validate(raise_exception=True)
data_content = schema.source
else:
with open(source_file, encoding="UTF-8") as file:
data_content = yaml.safe_load(file)
return data_content, data_type
plugins.set_config(env)
Dynamically update mkdocs configuration.
Based on the repo_slug (or folder name) load variables in
docs/_data/vars.yml, in docs/_data/repo.yml and update content of mkdocs
documentation accordingly.
Especially, if docs/_data/subrepo.yaml exists and define valid subrepos,
clone these subrepo and dynamically add them to the nav key of the mkdocs
configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
Source code in _data/plugins.py
def set_config(env: dict) -> None:
"""Dynamically update mkdocs configuration.
Based on the `repo_slug` (or folder name) load variables in
`docs/_data/vars.yml`, in `docs/_data/repo.yml` and update content of mkdocs
documentation accordingly.
Especially, if `docs/_data/subrepo.yaml` exists and define valid subrepos,
clone these subrepo and dynamically add them to the `nav` key of the mkdocs
configuration.
Arguments:
env: Mkdocs macro plugin environment dictionary.
"""
git_repo = git.Repo(search_parent_directories=True)
repo_slug = get_repo_slug(env, git_repo)
set_site_name(env, repo_slug)
set_site_desc(env, repo_slug)
set_site_url(env, repo_slug)
set_copyright(env, git_repo)
set_repo_name(env, repo_slug)
set_repo_url(env, repo_slug)
set_nav(env)
update_theme(env, repo_slug)
if "subrepo" in env.variables:
if (
not env.variables["internal_subdoc"]
and "monorepo" in env.conf["plugins"]
):
env.conf["plugins"].pop("monorepo")
else:
update_nav(env, env.variables["subrepo"], first_iteration=True)
plugins.set_copyright(env, git_repo)
Update content of the copyright key in env.conf.
Update the value of copyright key for mkdocs documentation based on (in
precedence order):
- Value of
copyrightinmkdocs.yml, - Value of
copyrightinenv.variables, fromdocs/_data/vars.yml, then, using this value:- Value of the year of the first commit of the repo holding the documentation and current year,
- Value of the current year only,
If no copyright key defined, neither in mkdocs.yml, nor in
docs/_data/vars.yml, then not copyright will be set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
git_repo |
Repo |
Git python object of the current repo. |
required |
Source code in _data/plugins.py
def set_copyright(env: dict, git_repo: git.Repo) -> None:
"""Update content of the `copyright` key in `env.conf`.
Update the value of `copyright` key for mkdocs documentation based on (in
precedence order):
- Value of `copyright` in `mkdocs.yml`,
- Value of `copyright` in `env.variables`, from `docs/_data/vars.yml`, then,
using this value:
- Value of the year of the first commit of the repo holding the
documentation and current year,
- Value of the current year only,
If no `copyright` key defined, neither in `mkdocs.yml`, nor in
`docs/_data/vars.yml`, then not copyright will be set.
Arguments:
env: Mkdocs macro plugin environment dictionary.
git_repo: Git python object of the current repo.
"""
if (
"copyright" not in env.conf or not env.conf["copyright"]
) and "copyright" in env.variables:
if git_repo.branches and git_repo.branches.master:
first_date = git_repo.commit(
git_repo.branches.master.log()[0].newhexsha
).committed_date
first_year = time.strftime("%Y", time.gmtime(first_date))
else:
first_year = time.strftime("%Y", time.localtime())
curr_year = time.strftime("%Y", time.localtime())
if first_year == curr_year:
env.variables["date_copyright"] = f"Copyright © {curr_year}"
else:
env.variables[
"date_copyright"
] = f"Copyright © {curr_year} - {curr_year}"
env.conf[
"copyright"
] = f"{env.variables['date_copyright']} {env.variables['copyright']}"
plugins.set_nav(env)
Update content of the nav key in env.conf.
Update the value of nav key for mkdocs documentation based on (in
precedence order):
- Value of
navinvars.ymlorextra.ymlindocs/_data/, allowing overloading of nav for forked repo. - Value of
navinmkdocs.yml
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
Source code in _data/plugins.py
def set_nav(env: dict) -> None:
"""Update content of the `nav` key in `env.conf`.
Update the value of `nav` key for mkdocs documentation based on (in
precedence order):
- Value of `nav` in `vars.yml` or `extra.yml` in `docs/_data/`, allowing
overloading of nav for forked repo.
- Value of `nav` in `mkdocs.yml`
Arguments:
env: Mkdocs macro plugin environment dictionary.
"""
if "nav" in env.variables and env.variables["nav"]:
env.conf["nav"] = env.variables["nav"]
plugins.set_repo_name(env, repo_slug)
Update content of the repo_name key in env.conf.
Update the value of repo_name key for mkdocs documentation based on (in
precedence order):
- Value of
repo_nameinmkdocs.yml, - Value of
repo_nameinenv.variables, fromdocs/_data/vars.yml, - Value of
nameinenv.variables[repo_slug], fromdocs/_data/repo.yml, then, depending on its value: - If value is
!!git_platform, then value ofrepo_namewill be set to the value ofenv.variables['git_platform']['name'], fromdocs/_data/vars.yml - Else, value is key
nameof `env.variables[repo_slug]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
repo_slug |
str |
Repo slug or name of the repo folder. |
required |
Source code in _data/plugins.py
def set_repo_name(env: dict, repo_slug: str) -> None:
"""Update content of the `repo_name` key in `env.conf`.
Update the value of `repo_name` key for mkdocs documentation based on (in
precedence order):
- Value of `repo_name` in `mkdocs.yml`,
- Value of `repo_name` in `env.variables`, from `docs/_data/vars.yml`,
- Value of `name` in `env.variables[repo_slug]`, from `docs/_data/repo.yml`,
then, depending on its value:
- If value is `!!git_platform`, then value of `repo_name` will be set to
the value of `env.variables['git_platform']['name']`, from
`docs/_data/vars.yml`
- Else, value is key `name` of `env.variables[repo_slug]
Arguments:
env: Mkdocs macro plugin environment dictionary.
repo_slug: Repo slug or name of the repo folder.
"""
if "repo_name" not in env.conf or not env.conf["repo_name"]:
if "repo_name" in env.variables:
env.conf["repo_name"] = env.variables["repo_name"]
elif "name" in env.variables[repo_slug]:
if env.variables[repo_slug]["name"] == "!!git_platform":
env.conf["repo_name"] = env.variables["git_platform"]["name"]
else:
env.conf["repo_name"] = env.variables[repo_slug]["name"]
plugins.set_repo_url(env, repo_slug)
Update content of the repo_url key in env.conf.
Update the value of repo_url key for mkdocs documentation based on (in
precedence order):
- Value of
repo_urlinmkdocs.yml, - Value of
repo_urlinenv.variables, fromdocs/_data/vars.yml, - Concatenation of the
urlofenv.variables['git_platform'], fromdocs/_data/vars.ymland valuegit_slug_with_namespaceinenv.variables[repo_slug], fromdocs/_data/repo.yml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
repo_slug |
str |
Repo slug or name of the repo folder. |
required |
Source code in _data/plugins.py
def set_repo_url(env: dict, repo_slug: str) -> None:
"""Update content of the `repo_url` key in `env.conf`.
Update the value of `repo_url` key for mkdocs documentation based on (in
precedence order):
- Value of `repo_url` in `mkdocs.yml`,
- Value of `repo_url` in `env.variables`, from `docs/_data/vars.yml`,
- Concatenation of the `url` of `env.variables['git_platform']`, from
`docs/_data/vars.yml` and value `git_slug_with_namespace` in
`env.variables[repo_slug]`, from `docs/_data/repo.yml`.
Arguments:
env: Mkdocs macro plugin environment dictionary.
repo_slug: Repo slug or name of the repo folder.
"""
if "repo_url" not in env.conf or not env.conf["repo_url"]:
if "repo_url" in env.variables:
env.conf["repo_url"] = env.variables["repo_url"]
elif "repo_url" in env.conf:
env.conf["repo_url"] = (
f"{env.variables['git_platform']['url']}"
+ f"{env.variables[repo_slug]['git_slug_with_namespace']}"
)
plugins.set_site_desc(env, repo_slug)
Update content of the site_desc key in env.conf.
Update the value of site_desc keys for mkdocs configuration based on (in
precedence order):
- Value of
site_descinmkdocs.yml, - Value of
site_descinenv.variables, fromdocs/_data/vars.yml, - Value of
descinenv.variables[repo_slug]fromdocs/_data/repo.yml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
repo_slug |
str |
Repo slug or name of the repo folder. |
required |
Source code in _data/plugins.py
def set_site_desc(env: dict, repo_slug: str) -> None:
"""Update content of the `site_desc` key in `env.conf`.
Update the value of `site_desc` keys for mkdocs configuration based on (in
precedence order):
- Value of `site_desc` in `mkdocs.yml`,
- Value of `site_desc` in `env.variables`, from `docs/_data/vars.yml`,
- Value of `desc` in `env.variables[repo_slug]` from `docs/_data/repo.yml`.
Arguments:
env: Mkdocs macro plugin environment dictionary.
repo_slug: Repo slug or name of the repo folder.
"""
if "site_desc" not in env.conf:
if "site_desc" in env.variables:
env.conf["site_desc"] = env.variables["site_desc"]
else:
env.conf["site_desc"] = env.variables[repo_slug]["desc"]
plugins.set_site_name(env, repo_slug)
Update content of the site_name key in env.conf.
Update the value of site_name keys for mkdocs documentation based on (in
precedence order):
- Value of
site_nameinmkdocs.yml, - Value of
site_nameinenv.variables, fromdocs/_data/vars.yml, - Value of
nameinenv.variables[repo_slug]fromdocs/_data/repo.yml.
If site_name key is not defined in mkdocs.yml then look to
docs/_data/vars.yml, if defined, else look to the the current repo
dictionary to set value of site_name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
repo_slug |
str |
Repo slug or name of the repo folder. |
required |
Source code in _data/plugins.py
def set_site_name(env: dict, repo_slug: str) -> None:
"""Update content of the `site_name` key in `env.conf`.
Update the value of `site_name` keys for mkdocs documentation based on (in
precedence order):
- Value of `site_name` in `mkdocs.yml`,
- Value of `site_name` in `env.variables`, from `docs/_data/vars.yml`,
- Value of `name` in `env.variables[repo_slug]` from `docs/_data/repo.yml`.
If `site_name` key is not defined in `mkdocs.yml` then look to
`docs/_data/vars.yml`, if defined, else look to the the current repo
dictionary to set value of `site_name`.
Arguments:
env: Mkdocs macro plugin environment dictionary.
repo_slug: Repo slug or name of the repo folder.
"""
if "site_name" not in env.conf or not env.conf["site_name"]:
if "site_name" in env.variables:
env.conf["site_name"] = env.variables["site_name"]
else:
env.conf["site_name"] = env.variables[repo_slug]["name"]
plugins.set_site_url(env, repo_slug)
Update content of the site_url key in env.conf.
Update the value of site_url key for mkdocs documentation based on (in
precedence order):
- Value of
site_urlinmkdocs.yml, - Value of
site_urlinenv.variables, fromdocs/_data/vars.yml, - Value of
site_base_urlinenv.variables, fromdocs/_data/vars.yml, concatenate withenv.variables[repo_slug]["url_slug_with_namespace"]fromdocs/_data/repo.yml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
repo_slug |
str |
Repo slug or name of the repo folder. |
required |
Source code in _data/plugins.py
def set_site_url(env: dict, repo_slug: str) -> None:
"""Update content of the `site_url` key in `env.conf`.
Update the value of `site_url` key for mkdocs documentation based on (in
precedence order):
- Value of `site_url` in `mkdocs.yml`,
- Value of `site_url` in `env.variables`, from `docs/_data/vars.yml`,
- Value of `site_base_url` in `env.variables`, from `docs/_data/vars.yml`,
concatenate with `env.variables[repo_slug]["url_slug_with_namespace"]`
from `docs/_data/repo.yml`.
Arguments:
env: Mkdocs macro plugin environment dictionary.
repo_slug: Repo slug or name of the repo folder.
"""
if "site_url" not in env.conf:
if "site_url" in env.variables:
env.conf["site_url"] = env.variables["site_url"]
elif "site_base_url" in env.variables:
site_url = (
env.variables["site_base_url"]
+ env.variables[repo_slug]["url_slug_with_namespace"]
)
env.conf["site_url"] = site_url
plugins.update_logo_src_repo(env, curr_repo, repo_name, path=None)
Update the content of the key logo and src_path of current repo.
Update value of keys logo and src_path of current repo holding the
documentation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
curr_repo |
Repo dictionary from |
required | |
repo_name |
str |
Name of the repo, |
required |
path |
str |
Absolute path of the location of the current repo. |
None |
Source code in _data/plugins.py
def update_logo_src_repo(
env: dict, curr_repo: dict, repo_name: str, path: str = None
) -> None:
"""Update the content of the key `logo` and `src_path` of current repo.
Update value of keys `logo` and `src_path` of current repo holding the
documentation.
Args:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
curr_repo : Repo dictionary from `repo.yml` file in `docs/_data/` in the
cloned subrepo,
repo_name: Name of the repo,
path: Absolute path of the location of the current repo.
"""
subpath = ""
if path:
subpath = os.path.join(path.replace(env.project_dir, ""), repo_name)
if "logo" not in curr_repo:
curr_repo["logo"] = os.path.join(
subpath, "assets", "img", "meta", f"{repo_name}_logo.png"
)
if "src_path" in curr_repo:
for i_src in curr_repo["src_path"]:
i_src = os.path.join(subpath, i_src)
env.conf["plugins"]["mkdocstrings"].config.data["handlers"][
"python"
]["setup_commands"].append(f"sys.path.append('{i_src}')")
plugins.update_nav(env, repo_dict, repo_parent=None, nav_parent=None, first_iteration=False)
Meta method which dynamically update the nav key of env.conf.
Recursively parse repo_dict (provided from subrepo.yml file in
docs/_data), depending on the content of the keys, method will:
- Update the list of
nav_parentandrepo_parent, - Call add_nav_entry to add missing entry to
navkey ofmkdocs.yml, - Call add_external_to_nav to add external
subrepo to
navkey ofmkdocs.yml, - Call add_internal_to_nav to add internal
subrepo to
navkey ofmkdocs.yml, - Recursively call itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
repo_dict |
Repo dictionary from |
required | |
repo_parent |
List of keys storing parent keys of the current
|
None |
|
nav_parent |
List of keys storing parents |
None |
|
first_iteration |
Simple boolean to know if it is the first recursive call of the method. |
False |
Source code in _data/plugins.py
def update_nav(
env: dict,
repo_dict: dict,
repo_parent: list = None,
nav_parent: list = None,
first_iteration=False,
) -> None:
"""Meta method which dynamically update the `nav` key of `env.conf`.
Recursively parse `repo_dict` (provided from `subrepo.yml` file in
`docs/_data`), depending on the content of the keys, method will:
- Update the list of `nav_parent` and `repo_parent`,
- Call [add_nav_entry][plugins.add_nav_entry] to add missing entry to `nav`
key of `mkdocs.yml`,
- Call [add_external_to_nav][plugins.add_external_to_nav] to add external
subrepo to `nav` key of `mkdocs.yml`,
- Call [add_internal_to_nav][plugins.add_internal_to_nav] to add internal
subrepo to `nav` key of `mkdocs.yml`,
- Recursively call itself.
Args:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
repo_dict : Repo dictionary from `subrepo.yml` file in `docs/_data/`
repo_parent : List of keys storing parent keys of the current
`repo_dict` from `subrepo.yml` file in `docs/_data`
nav_parent : List of keys storing parents `nav_entry` keys of the
current `repo_dict` from `subrepo.yml` file in `docs/_data`
first_iteration : Simple boolean to know if it is the first recursive
call of the method.
"""
for i_key in repo_dict:
if not nav_parent or first_iteration:
nav_parent = []
if not repo_parent or first_iteration:
repo_parent = []
if i_key == "nav_entry":
nav_parent.append(repo_dict["nav_entry"])
elif i_key == "internal":
for i_repo in repo_dict["internal"]:
if nav_parent[0] not in yaml.dump(env.conf["nav"]):
add_nav_entry(env.conf["nav"], nav_parent)
add_internal_to_nav(
env, env.conf["nav"], i_repo, repo_parent, nav_parent
)
elif i_key == "external":
for i_repo in repo_dict["external"]:
if nav_parent[0] not in yaml.dump(env.conf["nav"]):
add_nav_entry(env.conf["nav"], nav_parent)
add_external_to_nav(
env, env.conf["nav"], i_repo, repo_parent, nav_parent
)
else:
repo_parent.append(i_key)
update_nav(env, repo_dict[i_key], repo_parent, nav_parent)
plugins.update_subrepo(env, subrepo_dict, path, external)
Recursively parse env.variables['subrepo'].
Recursively parse dictionary env.variables['subrepo'], from file
docs/_data/subrepo.yaml. Depending on the key:
nav_entry: Do a recursion of this method,externalorinternal: Parse the list to update subrepo information
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
subrepo_dict |
dict |
Dictionary storing subrepo, |
required |
path |
str |
Absolute path of the location of the cloned subrepo, |
required |
external |
bool |
Boolean to know if current repo is an external subrepo. |
required |
Returns:
| Type | Description |
|---|---|
dict |
An updated dictionary of repo informations. |
Source code in _data/plugins.py
def update_subrepo(
env: dict, subrepo_dict: dict, path: str, external: bool
) -> dict:
"""Recursively parse `env.variables['subrepo']`.
Recursively parse dictionary `env.variables['subrepo']`, from file
`docs/_data/subrepo.yaml`. Depending on the key:
- `nav_entry`: Do a recursion of this method,
- `external` or `internal`: Parse the list to update subrepo information
Args:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
subrepo_dict: Dictionary storing subrepo,
path: Absolute path of the location of the cloned subrepo,
external: Boolean to know if current repo is an external subrepo.
Returns:
An updated dictionary of repo informations.
"""
return_dict = {}
for i_key in subrepo_dict:
if isinstance(subrepo_dict[i_key], list):
if i_key == "external":
external = True
elif i_key == "internal":
env.variables["internal_subdoc"] = True
return_dict.update(
update_subrepo_info(env, subrepo_dict[i_key], path, external)
)
elif i_key not in ["nav_entry"]:
return_dict.update(
update_subrepo(
env,
subrepo_dict[i_key],
os.path.join(path, i_key),
external,
)
)
return return_dict
plugins.update_subrepo_info(env, subrepo_list, path, external=False)
Clone subrepo, load repo information and update values if needed.
Recursively clone or pull repo defined from subpart of
env.variables['subrepo'], load repo information from this cloned or pulled
repo, i.e. load filedocs/_data/repo.yaml` in the subrepo, and update
needed keys.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
subrepo_list |
dict |
List of dictionary storing subrepo dict, |
required |
path |
str |
Absolute path of the location of the cloned subrepo, |
required |
external |
bool |
Boolean to know if current repo is an external subrepo. |
False |
Returns:
| Type | Description |
|---|---|
dict |
A updating dictionary storing subrepo information |
Source code in _data/plugins.py
def update_subrepo_info(
env: dict, subrepo_list: dict, path: str, external: bool = False
) -> dict:
"""Clone subrepo, load repo information and update values if needed.
Recursively clone or pull repo defined from subpart of
`env.variables['subrepo'], load repo information from this cloned or pulled
repo, i.e. load file `docs/_data/repo.yaml` in the subrepo, and update
needed keys.
Args:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
subrepo_list: List of dictionary storing subrepo dict,
path: Absolute path of the location of the cloned subrepo,
external: Boolean to know if current repo is an external subrepo.
Return:
A updating dictionary storing subrepo information
"""
return_dict = {}
for i_repo in subrepo_list:
subrepo_root = os.path.join(path, i_repo["name"])
if os.path.isdir(subrepo_root):
print(
f"{INFO_CLR}INFO [macros] - Pulling repo {i_repo['name']}{RESET_CLR}"
)
git_subrepo = git.Repo(subrepo_root)
git_subrepo.remotes.origin.pull("master")
else:
print(
f"{INFO_CLR}INFO [macros] - Cloning repo {i_repo['name']}{RESET_CLR}"
)
git.Repo.clone_from(i_repo["git_url"], subrepo_root)
if "subpath" in i_repo:
data_dir = os.path.join(
subrepo_root, i_repo["subpath"], "docs", "_data"
)
else:
data_dir = os.path.join(subrepo_root, "docs", "_data")
data_file = os.path.join(data_dir, f"{i_repo['name']}.yaml")
data, _ = load_yaml_file(data_dir, data_file)
for i_repo_info in data:
curr_repo = data[i_repo_info]
update_subrepo_logo_src(
env, curr_repo, i_repo_info, i_repo, path, external
)
return_dict.update(data)
return return_dict
plugins.update_subrepo_logo_src(env, curr_repo, repo_name, subrepo_dict, path, external)
Update the content of the key logo and src_path of subrepo.
Update value of keys logo and src_path of cloned subrepo, i.e. value
from file docs/_data/repo.yaml in the cloned subrepo, relative to the main
repo holding the documentation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required | |
curr_repo |
Repo dictionary from |
required | |
repo_name |
str |
Name of the repo, |
required |
subrepo_dict |
dict |
Dictionary of the repo as defined in file |
required |
path |
str |
Absolute path of the location of the cloned subrepo, |
required |
external |
bool |
Boolean to know if current repo is an external subrepo. |
required |
Source code in _data/plugins.py
def update_subrepo_logo_src(
env: dict,
curr_repo: dict,
repo_name: str,
subrepo_dict: dict,
path: str,
external: bool,
) -> None:
"""Update the content of the key `logo` and `src_path` of subrepo.
Update value of keys `logo` and `src_path` of cloned subrepo, i.e. value
from file `docs/_data/repo.yaml` in the cloned subrepo, relative to the main
repo holding the documentation.
Args:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
curr_repo : Repo dictionary from `repo.yml` file in `docs/_data/` in the
cloned subrepo,
repo_name: Name of the repo,
subrepo_dict: Dictionary of the repo as defined in file `subrepo.yaml`
in `docs/_data`,
path: Absolute path of the location of the cloned subrepo,
external: Boolean to know if current repo is an external subrepo.
"""
logo_subpath = ""
src_subpath = ""
if external:
logo_subpath = os.path.join(subrepo_dict["online_url"])
src_subpath = os.path.join(
path.replace(f"{env.project_dir}/", ""), repo_name
)
if "logo" not in curr_repo:
curr_repo["logo"] = os.path.join(
logo_subpath, "assets", "img", "meta", f"{repo_name}_logo.png"
)
if "src_path" in curr_repo:
for i_src in curr_repo["src_path"]:
i_src = os.path.join(src_subpath, i_src)
env.conf["plugins"]["mkdocstrings"].config.data["handlers"][
"python"
]["setup_commands"].append(f"sys.path.append('{i_src}')")
plugins.update_theme(env, repo_slug)
Update content of the theme key in env.conf.
If theme key is defined in docs/_data/vars.yml, this override the
content of the default theme key in mkdocs documentation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
dict |
Mkdocs macro plugin environment dictionary. |
required |
repo_slug |
str |
Repo slug or name of the repo folder. |
required |
Source code in _data/plugins.py
def update_theme(env: dict, repo_slug: str) -> None:
"""Update content of the `theme` key in `env.conf`.
If `theme` key is defined in `docs/_data/vars.yml`, this override the
content of the default `theme` key in mkdocs documentation.
Arguments:
env: Mkdocs macro plugin environment dictionary.
repo_slug: Repo slug or name of the repo folder.
"""
if "theme" in env.variables:
for i_key in env.variables["theme"]:
env.conf["theme"][i_key] = env.variables["theme"][i_key]
if "logo" not in env.conf["theme"] or not env.conf["theme"]["logo"]:
if "logo" in env.variables[repo_slug]:
env.conf["theme"]["logo"] = env.variables[repo_slug]["logo"]
else:
env.conf["theme"]["logo"] = os.path.join(
"assets", "img", "meta", f"{repo_slug}_logo.png"
)
if not env.conf["theme"]["icon"]:
env.conf["theme"]["icon"] = {}
if "icon" not in env.conf["theme"] or not env.conf["theme"]["icon"]:
env.conf["theme"]["icon"]["repo"] = env.variables["git_platform"][
"icon"
]
if "favicon" not in env.conf["theme"] or not env.conf["theme"]["favicon"]:
if "favicon" in env.variables[repo_slug]:
env.conf["theme"]["favicon"] = env.variables[repo_slug]["favicon"]
elif "logo" in env.variables[repo_slug]:
env.conf["theme"]["favicon"] = env.variables[repo_slug]["logo"]
else:
env.conf["theme"]["favicon"] = os.path.join(
"assets", "img", "meta", f"{repo_slug}_logo.png"
)
plugins.update_version(env)
Parse every tags of the repo to build a docs/versions.json.
To emulate mike version support for gitlab, this method will parse every
tags of the current repo holding the current documentation to create a file
versions.json which will be put in folder docs.
This is mainly used for the CI to build a documentation per repo tags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env |
Environment dictionary provided by mkdocs-macros-plugin |
required |
Source code in _data/plugins.py
def update_version(env: dict) -> None:
"""Parse every tags of the repo to build a `docs/versions.json`.
To emulate mike version support for gitlab, this method will parse every
tags of the current repo holding the current documentation to create a file
`versions.json` which will be put in folder `docs`.
This is mainly used for the CI to build a documentation per repo tags.
Arguments:
env : Environment dictionary provided by
[mkdocs-macros-plugin](https://mkdocs-macros-plugin.readthedocs.io/)
"""
if (
"version" not in env.variables
or "provider" not in env.variables["version"]
or env.variables["version"]["provider"] != "mike"
):
return
git_repo = git.Repo(search_parent_directories=True)
mike_version = []
last_major = -1
last_minor = -1
last_patch = str(-1)
for i_tag in git_repo.tags:
i_tag = yaml.dump(i_tag.path)
i_tag = re.sub(".*v", "", i_tag).split(".")
major = int(i_tag[0])
minor = int(i_tag[1])
patch = str()
for i_remain_tag in i_tag[2:]:
if i_remain_tag and i_remain_tag not in ("", "\n"):
i_remain_tag = i_remain_tag.replace("\n", "")
if not patch:
patch = f"{i_remain_tag}"
else:
patch = f"{patch}.{i_remain_tag}"
if major > last_major:
if last_major >= 0:
mike_version.append(
{
"version": f"{last_major}.{last_minor}",
"title": f"{last_major}.{last_minor}.{last_patch}",
"aliases": [],
}
)
last_major = major
last_minor = -1
if minor > last_minor:
if last_minor >= 0:
mike_version.append(
{
"version": f"{last_major}.{last_minor}",
"title": f"{last_major}.{last_minor}.{last_patch}",
"aliases": [],
}
)
last_minor = minor
last_patch = str(-1)
if patch > last_patch:
last_patch = str(patch)
mike_version.append(
{
"version": f"{last_major}.{last_minor}",
"title": f"{last_major}.{last_minor}.{last_patch}",
"aliases": ["latest"],
}
)
mike_version.reverse()
with open(
os.path.join(env.project_dir, "docs", "versions.json"),
"w",
encoding="UTF-8",
) as version_file:
json.dump(mike_version, version_file, indent=2)