Add Config::base_url to resolve relative links (#287) - #288
Open
jaredlynskey wants to merge 1 commit into
Open
Conversation
An <a href=/login> renders as /login, which only means something to a reader who has the page it came from. When the output is consumed away from that context -- feeding a page to an LLM, or storing the Markdown -- those links cannot be followed. Config::base_url(...) resolves them per RFC 3986 section 5.3. Absolute URLs and non-HTTP schemes (mailto:, data:, tel:) are passed through untouched, and with no base URL set the output is unchanged. Resolution is implemented in-crate rather than by taking a dependency on the url crate, since only reference resolution is needed here. Closes jugglerchris#287
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the request in #287.
What it does
Adds
Config::base_url(...), which resolves relativehrefs while rendering:<a href="/login">renders ashttps://example.com/logininstead of/login.Behaviour
Resolution follows RFC 3986 §5.3:
https://other.example/x,mailto:…,data:…,tel:…//cdn.example/x.js/loginc.html,../c.html#frag,?q=1With no base URL set the output is byte-identical to before — the existing 128 tests pass unchanged, and the option defaults to
None.On the implementation
Resolution is done in-crate (
src/url_resolve.rs, ~110 lines) rather than by adding theurlcrate. Only reference resolution is needed and this crate's dependency list is deliberately small, so pulling in a full URL parser for it seemed the wrong trade — but I'm happy to switch tourlbehind an optional feature if you'd prefer that; it would be a small change.I put the resolution at the point the
hrefis read inprocess_dom_node, so it happens once during tree building rather than in the decorators. That keeps every decorator and output format getting resolved links for free. If you'd rather it sat elsewhere I'm glad to move it.Tests
url_resolvecovering each reference form, non-HTTP schemes, an unusable base, and dot segments at the roottest_html_confpathOne worth calling out:
/../../etcinitially resolved tohttps://example.cometc, because..popped the leading empty segment and took the root separator with it. RFC 3986 §5.2.4 discards those instead, which is what it now does — there's a test pinning it.cargo testpasses (139 lib + 3 doc),cargo fmt --checkis clean, and it builds with--all-featuresand--no-default-features.