pymdown-extensions icon indicating copy to clipboard operation
pymdown-extensions copied to clipboard

Snippets - Inserting markdown, is it possible to custom the level for inherited headers?

Open Guts opened this issue 4 years ago • 9 comments

When embedding a markdown file into another one, is there a way to control how headers are transformed? As performed in the markdown-include extension : https://github.com/cmacmackin/markdown-include#configuration.

If not, could it be a future feature?

Guts avatar Aug 12 '20 10:08 Guts

I can already think of multiple corner cases that would break markdown-include's implementation. I can see it parsing headers in fences when you don't want it to. I can see this not playing well with other of our features...since it runs as a preprocessor, it has no context of other files. It may work in certain scenarios, but it will not work in all, at least the way markdown-include implements it.

You would be better off implementing something like a relative header feature. I could see a Tree processor looking for any headers that have data-header-rel="1" where the value instructs the processor how much to increase the header level by. These would stack of course. When done, I imagine you could reset it data-header-rel="-1". This would have to run before the toc extension processes the headers.

# Header Level 1

# Header Level 3 {: data-header-rel="2"}

# Header Level 4 {: data-header-rel="1"}

# Header Level 5 {: data-header-rel="1 -4"}

# Header Level 1
<h1>Header Level 1</h1>
<h3>Header Level 3</h3>
<h4>Header Level 4</h4>
<h5>Header Level 5</h5>
<h1>Header Level 1</h1>

This would seem to avoid the pitfalls of markdown-include by not relying on the processor that has no context to make context decisions.

@gir-bot remove S: triage @gir-bot add T: feature, S: maybe, C: snippets

facelessuser avatar Aug 12 '20 13:08 facelessuser

Nice! Where could it be implemented in the source code? By there maybe:

https://github.com/facelessuser/pymdown-extensions/blob/f121e0816571ef2eadfa8cc6ba87fe169736a6e1/pymdownx/snippets.py#L62

Guts avatar Aug 12 '20 18:08 Guts

Most likely, the best approach would be to create a separate TreeProcessor. It would run at a later time than the Snippet preprocessor.

The snippet creator would need to doctor the headers as I mentioned earlier (and also enable the attr_list extension from Python Markdown).

The TreeProcessor would execute right before toc and would walk the tree changing the header levels as dictated by the data-header-rel (or whatever we call it). Those attributes would then get stripped out. Then toc could do its thing on the headers as desired.

facelessuser avatar Aug 12 '20 18:08 facelessuser

When you write:

the best approach would be to create a separate TreeProcessor

You mean, creating something like that somewhere in snippets.py:

from markdown.treeprocessors import Treeprocessor

[...]

class SnippetTreeprocessor(Treeprocessor):
    """Snippet Treeprocessor."""

or inheriting directly from attr_list?

https://github.com/Python-Markdown/markdown/blob/370e17b3923d7d8f4709652bc24b695271a0210d/markdown/extensions/attr_list.py#L65

I'm asking a lot but it to determine if I'm feelling able to psuh a PR or not.

Guts avatar Aug 13 '20 07:08 Guts

Yes, in snippets. When called, it would probably exit immediately if attr_list is not enabled.

facelessuser avatar Aug 13 '20 12:08 facelessuser

Well, I take that back. It probably shouldn't care if attr_list is enabled. But attr_list would be the way to set those.

facelessuser avatar Aug 13 '20 14:08 facelessuser

I say this because you could probably do manual headers and it would work as well:

<h2 data-header-rel="2">Header text</h2>

facelessuser avatar Aug 13 '20 14:08 facelessuser

I'm not positive I'm totally following the proposed solution, so please forgive the noise if what I'm saying doesn't make sense. But—looking at the implementation in markdown-include, there's also support for headingOffset, where you pass in a specific header offset. Would something like that work here? As in, along with the snippet filename, pass in an optional offset by which snippets should bump any Markdown headers it finds in the included content?

(This is a great tool, thanks!)

bradumbaugh avatar Mar 21 '21 23:03 bradumbaugh

Currently, there is no support for special header logic. Snippets, in its current form, simply inserts the content where you reference it (indented appropriately).

There has been no real decision yet on what the final solution will look like, assuming we implement it.

facelessuser avatar Mar 21 '21 23:03 facelessuser