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

Internal links with ./ should be relative, rather than absolute #686

Closed
chris-morgan opened this issue May 17, 2019 · 7 comments
Closed
Labels
done in pr Already done in a PR enhancement

Comments

@chris-morgan
Copy link
Contributor

In #19, internal links were added, but in a syntactically abnormal way: a leading ./ means an absolute URL, relative to the content directory rather than the current file.

This is a really bad idea, and a serious design bug: it wreaks havoc with the expected semantics of URLs and relative paths, leading to substantial surprise among users, and breaking tooling that people use. In Vim, for example, gf goes to the file under the cursor, and it treats ./foo.md as a relative path, but if the current file is content/bar/baz.md, it looks for content/bar/foo.md rather than content/foo.md.

This design decision was briefly questioned in #19 (comment), and the response was this:

That's intended, I think it makes more sense that way: you can move the file around but the links will stay valid.

Well, you can move the source file around, but not the destination file. If you rename a file, any files that link to it will still need to be updated.

My real counterpoint to this argument is that one of the most common forms of content moving is directory renaming; and going for absolute URLs instead of relative makes that harder, because now all pages inside the section need to have all their links updated, rather than them just working.


Really, it should be parsing the whole thing as a URL, with the content directory being the site root. Thus, things like https://… and //… will be untouched, /foo will be understood to be relative to the content directory, ../foo to the parent directory (whatever that may be, up to but not exceeding the content directory), and ./foo and foo relative to the current directory.

Then, let people decide for themselves whether they want to use relative or absolute URL styles—there are advantages and disadvantages to both approaches. In some moods I prefer absolute, because you can search for it in the source more easily; in others I prefer relative, because it’s shorter!

There is always the hazard with this that not all links that start with /, ./ or other such things are internal links—I might write /foo/, for example, rather than /foo.md. If you really want a special prefix, go for a URI scheme, e.g. site:foo.md; just don’t use ./foo.md, because it’s very confusing.

This will be a breaking change. It should be made sooner rather than later, because it will cause pain for users whenever it’s done.


(I’m questioning this now because we’re in the process of moving fastmail.com from a long-in-the-tooth homegrown Markdown.pl system to Zola, and use relative links, with ./ and ../, extensively in our help pages. We’re going to update the links in various ways anyway, but it brought my attention to this design bug.)

@Keats
Copy link
Collaborator

Keats commented May 17, 2019

So I am kind of on the fence there. I agree that it shouldn't overtake real relative links but adding a protocol feels a bit weird.
How about something that gets out of the actual links syntax and use something like @/foo.md where @ is equal to the contents directory? This is kind of equivalent of webpack/TS alias if you're familiar with that.

cc @phil-opp who mentioned that first

@Keats
Copy link
Collaborator

Keats commented May 17, 2019

I’m questioning this now because we’re in the process of moving fastmail.com

❤️ (as a customer)

@chris-morgan
Copy link
Contributor Author

Yeah, I like an @ prefix for internal links, makes it fairly clear there’s magic going on, since it’s very unlikely to collide with anything real, and is still lightweight.

Further refinements of the idea:

1a. Is @ a magic directory like . or .., meaning “the path to the contents directory”, or
1b. is @ a namespace for internal links, a virtual filesystem rooted in contents, meaning “resolve what follows as an internal link, or die on if unresolvable”—to guard strongly against broken links.

​2a. Should only full content paths be supported, with this @/ prefix, or
2b. allow relative paths as well? Under 1b, that would mean the likes of @foo.md (I wouldn’t complain if that were banned, requiring /, ./ or ../), @./foo.md and @../foo.md; under 1a, drop the @ prefix.

Without 2b the difference between 1a and 1b is theoretical only, but even so I much prefer the semantics of 1b over 1a. It’s just crying out for flawless broken link detection, which would feel mildly contrived under 1a semantics. I therefore strongly recommend 1b.

Then for 2, there are pros and cons both ways. Relative links are often nice to be able to write (though even without this, you’ll still be able to write relative links, it’ll just have to be as they will appear in the generated HTML rather than as links to the source files), and I think it is a natural thing to expect to be able to write. For involved or large content structures, relative links are a boon indeed.

On the other hand, full content paths make for easier global search and replace (you can use naive tools instead of needing clever ones), and the presence of a dedicated operator for the purpose, ideally shoved down people’s throats as the Right Way to Do It, will gently discourage them from writing things in other ways—though some will always grumble about the lack of support for relative paths.

I don’t know which way to turn on the point; I lean in one direction, and immediately turn back, yearning for the other. Fortunately I have not been made a pillar of salt. Or for another classical allusion—2b, or not 2b?

I… think I’m leaning towards allowing relative links. But at the same time I may have convinced myself not to use them even if they’re supported! (But probably not.)

@Keats
Copy link
Collaborator

Keats commented May 17, 2019

It would definitely be 1b, that's currently how internal links are implemented.

2b, or not 2b?

💯

I would go with 2a to start with I think. As you say it's much easier to grep: @../../../_index.md is not great for example. Moving it around, the link might still be valid but pointing to a different section with no warning since it does resolve.
We can add relative linking later if needed but I think it is strictly worse than writing the full path so there would need to be a very very good argument for it.

@Keats
Copy link
Collaborator

Keats commented May 27, 2019

It's in the next branch if you want to give it a try @chris-morgan

@Keats Keats added done in pr Already done in a PR enhancement labels May 27, 2019
@Keats Keats closed this as completed in ec61a57 Jun 22, 2019
@Simran-B
Copy link

Simran-B commented Jan 8, 2020

Late to the party, but let me add another point to this discussion which was apparently not considered yet:

Clickable links in your code editor. When I edit content, I want to be able to add and immediately test links, in my case in VS Code with Alt+Click. I don't even have to save the file and let the site rebuild to find out whether the link is working or not. I still want a link checker to verify everything of course, but a quick feedback on links is really handy. It also lets you navigate the content and edit related pages quicker.

With a special syntax like @path/to/file, it is no longer clickable, or rather not be found because at-sign is considered to be part of the folder name (at least in VS Code that is). There does not seem to be a universally supported syntax for "project root" / "content root" unfortunately. 😢

If I understand correctly, then . and .. are also supported and will be resolved relatively to the current directory? Such links should then be clickable and open the correct file in code editors. Or is this something that still has to be implemented?

I wished that there was a solution to make @ links open the correct files as well, but I guess that would require serious hacking of the respective code editor, as it has to figure out what @ means based on some configuration file.

If @ stops users from opening the wrong files, then that's a win even if an error pops up if you try to follow the link. I must say that I like the syntax a lot better than what Jekyll does for instance:

[Link to a document]({% link _collection/name-of-document.md %})

Using a tag is really cumbersome. What I actually do at the moment is to reference the output file:

[Link to a document](_collection/name-of-document.html)

It obviously has the drawback of not being clickable… Jekyll wouldn't change .md to .html, but Gitbook does this. I can't recall if they supported a way to refer to the book root, or if everything was based on relative links - I believe there were differences between Markdown files and images, which was rather odd.

@Simran-B
Copy link

Simran-B commented Jan 9, 2020

Antora has an interesting approach: https://docs.antora.org/antora/2.2/page/page-id/
The reference by page ID, which is constructed from the properties of the source document. But it doesn't solve the clickable links problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
done in pr Already done in a PR enhancement
Projects
None yet
Development

No branches or pull requests

3 participants