Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for relative base_path in markdown_extensions #2154

Closed
dersimn opened this issue Jul 17, 2020 · 15 comments · Fixed by #3258
Closed

Support for relative base_path in markdown_extensions #2154

dersimn opened this issue Jul 17, 2020 · 15 comments · Fixed by #3258

Comments

@dersimn
Copy link

dersimn commented Jul 17, 2020

Many extensions need to know the base path of the currently rendered Markdown file, as they are supposed to include assets relative to the markdown file. Two of them are:

Both make use of the config variable base_path for including other files, so in order to configure it, you would specify:

markdown_extensions:
  - pymdownx.snippets:
      base_path: docs
  - markdown_include.include:
      base_path: docs

Currently

Please take a look at this example repository.

|-- README.md
|-- docs
|   |-- big_topic
|   |   |-- index.md
|   |   `-- more_important_code.c
|   |-- index.md
|   `-- smaller_topic
|       |-- hello_world.c
|       `-- index.md
`-- mkdocs.yml

Currently you would have to include the *.c files with their full path, so in both files you would have to write:

    --8<-- "smaller_topic/hello_world.c"
    --8<-- "big_topic/more_important_code.c"

Why is this bad?

This is fine for Markdown files that are created and maintained for just one website, but we are currently including generic sub topics into our site that are shared among many repositories via git submodule. For e.g. some introduction topic on how to set up Docker. It's obvious that include paths must be relative to the Markdown file in this case, like:

    --8<-- "hello_world.c"
    --8<-- "more_important_code.c"

Desirable solution

If we want to be able to specify relative paths in every Markdown file, the base_path variable need to change with every Markdown file to be rendered, so it can't simply be included in mkdocs.yml.
This makes my feature request different from #998 #777 #761, because I'm not able to alter the .md files as they are shared over multiple projects.

It would be nice if we could specify something like

markdown_extensions:
  - pymdownx.snippets:
      base_path: $relative
  - markdown_include.include:
      base_path: $relative
  - one of many other extensions that use exacly 'base_path' as variable:
      base_path: $relative

that would then make MkDocs add the currently valid path as base_path variable for each rendered Markdown file.

This is an issue for the one who calls the plugin, and not the plugin itself, as an additional (dynamic) base_path must be exchanged at this point in code:

md = markdown.Markdown(
    extensions=extensions,
    extension_configs=config['mdx_configs'] or {}
)

Currently (with the upper config from my example), extension_configs would contain something in the structure of this:

extension_configs = {
    'pymdownx.snippets': {
        'base_path': '$relative'
    },
    'markdown_include.include': {
        'base_path': '$relative'
    }
}

We need to replace $relative here with the proper path depending on the current navigation.

@ahojukka5
Copy link

I just first time tried pymdownx.snippets and yeah, indeed, this would be an awesome feature. I'm still structuring my document tree and probably I have to change all those paths to snippets yet so many times...

dersimn added a commit to dersimn/mkdocs that referenced this issue May 11, 2021
Signed-off-by: Simon Christmann <simon@christmann.email>
@dersimn
Copy link
Author

dersimn commented May 11, 2021

@jorgegomezcq
Copy link

Hi, what's the status on this?

@pawamoy
Copy link
Sponsor Contributor

pawamoy commented Mar 24, 2023

I don't think there was any progress. But I didn't know about this issue and I opened this discussion some time ago: #2833

@pawamoy
Copy link
Sponsor Contributor

pawamoy commented Mar 24, 2023

I actually very much like the idea of variables provided by MkDocs: $docs_dir, $config_dir, and whatever else is relevant. I don't care about the syntax: there might be a way to use env vars instead, if MkDocs itself exports them:

markdown_extensions:
- pymdownx.snippets:
    base_path: !ENV MKDOCS_CONFIG_DIR

Depending on the order of things, env vars might be impossible to use. This might need a post-process step where $config_dir and others are replaced with their values.

@oprypin
Copy link
Contributor

oprypin commented Jun 11, 2023

I think I'd like to make it work like this:

markdown_extensions:
  - pymdownx.snippets:
      base_path:
        - !relative  # Relative to current.md
        - !docs_dir  # Relative to docs_dir
        - !config_dir  # Relative to mkdocs.yml

The issue is that indeed now we need some way to dig through the parsed YAML and find and replace the placeholders. There doesn't seem to be any standard way for that.

Alternatively for a solution that's much much cleaner on MkDocs side but worse on the extension side, the value would actually be dynamically computed, but then we'd require each destination extension to call str(value) on anything that expects these dynamic values.

Otherwise of course places like this one get an error
https://github.com/facelessuser/pymdown-extensions/blob/67b084e6d14cbfa0c6c457e14aeb0e007f67a91a/pymdownx/snippets.py#L161
TypeError: stat: path should be string, bytes, os.PathLike or integer, not _YamlPlaceholder

@oprypin
Copy link
Contributor

oprypin commented Jun 11, 2023

That gave me an idea- the value will respond not only to __str__ but also to __fspath__, totally avoiding at least this class of errors. So this works seamlessly with current pymdownx.snippets with the example above.

Linked a pull request accordingly.

cc @facelessuser

@facelessuser
Copy link
Contributor

@oprypin does this allow things like !docs_dir/some/child/dir?

@oprypin
Copy link
Contributor

oprypin commented Jun 12, 2023

No.
That's not a valid YAML tag syntax and I don't have good ideas how to make this work in a different way.

@oprypin
Copy link
Contributor

oprypin commented Jun 12, 2023

Hm actually... I suppose !docs_dir some/child/dir is valid YAML syntax

@oprypin
Copy link
Contributor

oprypin commented Jun 12, 2023

Maybe this idea would be better:

        - !relative  # Relative to current.md
        - !relative $docs_dir  # Relative to docs_dir
        - !relative $docs_dir/some/child/dir
        - !relative $config_dir  # Relative to mkdocs.yml

@pawamoy
Copy link
Sponsor Contributor

pawamoy commented Jun 12, 2023

I find "relative" a bit confusing, but cannot find a better alternative. "path" would be too vague. "relpath" maybe too technical. In fact, relative-ness is not in question here since we use a variable ($docs_dir, $config_dir) which could return an absolute path for all we know. configpath? specialpath? dynamicpath? buildpath? docspath? mkdocspath?

@oprypin
Copy link
Contributor

oprypin commented Jun 18, 2023

Any other ideas? ¯\_(ツ)_/¯

@pawamoy
Copy link
Sponsor Contributor

pawamoy commented Jun 18, 2023

Nope, just go with what you prefer :)

@oprypin
Copy link
Contributor

oprypin commented Jun 18, 2023

The other thing that's bugging me is this arbitrary $ symbol that has no precedent in MkDocs configs so far. There would be some precedent for making it like !relative {docs_dir} but that's more confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants