Skip to content

mkdocsbackend

Class info

Classes

Name Children Inherits
MkDocsBackend
mkdocs_mknodes.backends.mkdocsbackend

    🛈 DocStrings

    MkDocsBackend

    Bases: BuildBackend

    Source code in mkdocs_mknodes/backends/mkdocsbackend.py
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    class MkDocsBackend(buildbackend.BuildBackend):
        def __init__(
            self,
            files: files_.Files | None = None,
            config: mkdocsconfig.Config | MkDocsConfig | str | os.PathLike[str] | None = None,
            directory: str | os.PathLike[str] | None = None,
        ):
            """Constructor.
    
            Args:
                files: A Files collection to use for new files
                config: An MkDocs config
                directory: The build directory
            """
            match config:
                case mkdocsconfig.Config():
                    self._config = config._config
                case MkDocsConfig():
                    self._config = config
                case _:
                    self._config = mkdocsconfig.Config(config)._config
            self.directory = upath.UPath(directory or ".")
            files_map = {pathlib.PurePath(f.src_path).as_posix(): f for f in files or []}
            self._mk_files: collections.ChainMap[str, files_.File] = collections.ChainMap(
                {},
                files_map,
            )
            self.builder = mkdocsbuilder.MkDocsBuilder(self._config)
    
        def _get_parser(self) -> markdown.Markdown:
            """Return a markdown instance based on given config."""
            return markdown.Markdown(
                extensions=self._config.markdown_extensions,
                extension_configs=self._config.mdx_configs,
            )
    
        @property
        def files(self) -> files_.Files:
            """Access the files as they currently are, as a MkDocs [Files][] collection.
    
            [Files]: https://github.com/mkdocs/mkdocs/blob/master/mkdocs/structure/files.py
            """
    
            def file_sorter(f: files_.File) -> tuple[str, ...]:
                parts = pathlib.PurePath(f.src_path).parts
                return tuple(
                    chr(f.name != "index" if i == len(parts) - 1 else 2) + p
                    for i, p in enumerate(parts)
                )
    
            files = sorted(self._mk_files.values(), key=file_sorter)
            return files_.Files(files)
    
        def write_files(self, files):
            for k, v in files.items():
                if pathlib.Path(k).name == "SUMMARY.md":
                    continue
                logger.debug("%s: Writing file to %r", type(self).__name__, str(k))
                self._write_file(k, v)
    
        def write_assets(self, assets):
            for asset in assets:
                if asset.target_dir == "docs_dir":
                    abs_path = upath.UPath(self._config.docs_dir) / asset.filename
                    logger.info("Writing asset %s...", abs_path)
                    pathhelpers.write_file(asset.content, abs_path)
                else:
                    path = (pathlib.Path("assets") / asset.filename).as_posix()
                    abs_path = upath.UPath(self._config.site_dir) / path
                    pathhelpers.write_file(asset.content, abs_path)
    
        def write_css(self, css_files):
            for css in css_files:
                if isinstance(css, resources.CSSText):
                    path = (pathlib.Path("assets") / css.resolved_filename).as_posix()
                    self._config.extra_css.append(path)
                    abs_path = upath.UPath(self._config.site_dir) / path
                    logger.info("Registering css file %s...", abs_path)
                    pathhelpers.write_file(css.content, abs_path)
                else:
                    logger.debug("Adding remote CSS file %s", css)
                    self._config.extra_css.append(str(css))
    
        def write_js_links(self, js_links):
            for file in js_links:
                logger.debug("Adding remote JS file %s", str(file))
                val = config_options.ExtraScriptValue(str(file))
                val.async_ = file.async_
                val.defer = file.defer
                val.type = file.typ
                self._config.extra_javascript.append(val)
    
        def write_js_files(self, js_files):
            for file in js_files:
                path = (pathlib.Path("assets") / file.resolved_filename).as_posix()
                val = config_options.ExtraScriptValue(str(path))
                val.async_ = file.async_
                val.defer = file.defer
                val.type = file.typ
                self._config.extra_javascript.append(path)
                abs_path = upath.UPath(self._config.site_dir) / path
                logger.info("Registering js file %s...", abs_path)
                pathhelpers.write_file(file.content, abs_path)
    
        def collect_extensions(self, extensions):
            if extensions:
                for ext_name in extensions:
                    if ext_name not in self._config.markdown_extensions:
                        logger.info("Adding %s to extensions", ext_name)
                        self._config.markdown_extensions.append(ext_name)
                self._config.mdx_configs = serializefilters.merge(
                    self._config.mdx_configs,
                    extensions,
                )
    
        def write_templates(self, templates):
            if not self._config.theme.custom_dir:
                logger.warning("Cannot write template. No custom_dir set in config.")
                return
            path = upath.UPath(self._config.theme.custom_dir)
            for template in templates:
                md = self._get_parser()
                if html := template.build_html(md):
                    target_path = path / template.filename
                    logger.info("Creating %s...", target_path.as_posix())
                    pathhelpers.write_file(html, target_path)
    
        def _write_file(self, path: str | os.PathLike[str], content: str | bytes):
            path = pathlib.PurePath(path).as_posix()
            file_for_path = self.builder.get_file(path, src_dir=self.directory)
            new_path = upath.UPath(file_for_path.abs_src_path)
            target_path = None
            if path not in self._mk_files:
                new_path.parent.mkdir(exist_ok=True, parents=True)
                self._mk_files[path] = file_for_path
                target_path = new_path
    
            f = self._mk_files[path]
            source_path = upath.UPath(f.abs_src_path)
            if source_path != new_path:
                self._mk_files[path] = file_for_path
                pathhelpers.copy(source_path, new_path)
                target_path = new_path
            pathhelpers.write_file(content, target_path or source_path)
    

    files property

    files: Files
    

    Access the files as they currently are, as a MkDocs Files collection.

    __init__

    __init__(
        files: Files | None = None,
        config: Config | MkDocsConfig | str | PathLike[str] | None = None,
        directory: str | PathLike[str] | None = None,
    )
    

    Constructor.

    Parameters:

    Name Type Description Default
    files Files | None

    A Files collection to use for new files

    None
    config Config | MkDocsConfig | str | PathLike[str] | None

    An MkDocs config

    None
    directory str | PathLike[str] | None

    The build directory

    None
    Source code in mkdocs_mknodes/backends/mkdocsbackend.py
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    def __init__(
        self,
        files: files_.Files | None = None,
        config: mkdocsconfig.Config | MkDocsConfig | str | os.PathLike[str] | None = None,
        directory: str | os.PathLike[str] | None = None,
    ):
        """Constructor.
    
        Args:
            files: A Files collection to use for new files
            config: An MkDocs config
            directory: The build directory
        """
        match config:
            case mkdocsconfig.Config():
                self._config = config._config
            case MkDocsConfig():
                self._config = config
            case _:
                self._config = mkdocsconfig.Config(config)._config
        self.directory = upath.UPath(directory or ".")
        files_map = {pathlib.PurePath(f.src_path).as_posix(): f for f in files or []}
        self._mk_files: collections.ChainMap[str, files_.File] = collections.ChainMap(
            {},
            files_map,
        )
        self.builder = mkdocsbuilder.MkDocsBuilder(self._config)