mdzk-rs / mdzk

General-purpose interface to connected notes
https://mdzk.app
Mozilla Public License 2.0
234 stars 18 forks source link

Configurable link-style generation #103

Open MatteoJoliveau opened 2 years ago

MatteoJoliveau commented 2 years ago

Hi, it's me again!

Currently fn fix_link(dest: CowStr) -> CowStr converts markdown links from something/something.md to something/something.html. This makes it difficult to support clean URLs (aka /my/page instead of /my/page.html). In my case, I actually generate HTML files as independent index.html files in dedicated directories. For instance, this is the conversion my SSG performs:

Source File Generated File Live URL
README.md index.html /
an-article.md an-article/index.html /an-article
a/nested/README.md a/nested/index.html /a/nested

Proposed solution

Have the Vault accept an additional (optional) configuration flag that asks whether to generate clean URLs or not. Since the output of the actual HTML files is up to the caller, the only thing this flag does is change the behaviour of fix_link(). The flag can be false by default to keep the current behaviour as the default one.

/// Generate /my/page.html and /categories/README.html links. Default behaviour
mdzk::VaultBuilder::default().source(out_dir).clean_urls(false)

/// Generate /my/page and /categories links
mdzk::VaultBuilder::default().source(out_dir).clean_urls(true)

Currently, I worked around this by parsing the generated HTML and applying some heuristics based on the current note path, fixing relative links and cleaning up file extensions, but it's cumbersome (around 60 LOC of pretty inefficient string manipulation) and the built-in solution would be much cleaner and more efficient.

Alternatives I considered

One alternative would be to skip Note::as_html and implement Markdown parsing myself using pulldown-cmark. That could work, and I may have to do it anyway in the future for stuff like custom HTML nodes, but I still think this could be a useful feature for use-cases that do not require such fine-grained control over the parsed DOM.

MatteoJoliveau commented 2 years ago

Actually, since HTML generation doesn't happen until Note::as_html is called, the flag can just be passed to the function, maybe as an enum to be more explicit.

note.as_html(LinkStyle::Clean)

This would be an API breaking change tho

kmaasrud commented 2 years ago

Great question, and something that definitely needs to be considered! However, firstly we need to establish the following: Seeing as you want clean links to all your internal pages, can we assume the option you want should only apply to wikilinks?

Excited to hear your thoughts!

MatteoJoliveau commented 2 years ago

I think a pluggable interface to customize link generation is a very good idea! It would allow downstream projects to do what they wish with links without bloating mdzk with a ton of conditional logic.

Do you have a roadmap for #77? I can take a swing at implementing it if you have a design in mind for the API

kmaasrud commented 2 years ago

@MatteoJoliveau check out #104! It's still a work in progress, but you should get an idea of how I'm imagining the API to be. Feel free to leave any suggestions there, if you'd like 😄