eleventy
eleventy copied to clipboard
Allow pathPrefix to be blank so navigation is relative
Is your feature request related to a problem? Please describe.
I'm creating a site in a subdirectory of a site. This site is 1-level deep and I want all navigation links to be relative (ie: colours.html instead of /colours.html)
Describe the solution you'd like
If pathPrefix is blank, then the prefix added to paths should also be blank.
Describe alternatives you've considered
I've also tried setting pathPrefix to ./ and ../docs/ (where "docs" is the directory I'm outputting the site to. In both cases, the leading dots get stripped.
My current fix is to write a custom filter that strips leading slashes, then create my own navigation rather than using the built-in eleventyNavigationToHTML.
Additional context
Currently, due to #302, a blank pathPrefix get translated to "/". This kind of seems like a bug because "/" != "" and is not obvious.
07/04/22 Hi folks, I am looking for how to remove the leading "/" from URLs using {{post.url}} if that is possible using eleventy's configuration. Within eleventy.js I have set (pathPrefix: '') to empty. I still get a "/" so that: /blog/my-article.html I want: blog/my-second-article.html (no leading slash). If this isn't possible, can someone please direct me to a work-around where I use a templating block instead?
Not sure if something like this would work for you.
Basically it caches the built-in url filter (as origUrlFilter), and then overwrites the default url filter with our custom version which removes a leading "/" (unless the URL in question starts with a protocol-relative URL; ie: "//hostname")
// .eleventy.js
module.exports = function (eleventyConfig) {
const origUrlFilter = eleventyConfig.getFilter("url");
eleventyConfig.addFilter("url", function (url, pathPrefixOverride) {
const _url = origUrlFilter(url, pathPrefixOverride);
if (_url.startsWith("/") && !_url.startsWith("//")) {
return _url.slice(1);
}
return _url;
});
return {
dir: {
input: "src",
output: "www",
},
pathPrefix: "salmon",
};
};
Hi Peter thank you for your reply and suggestion. I tried it but I could not get it to work. I tried with and without the "salmon" and other things as well.
I have a permalink function to give me documents.html in my .eleventy.js file.
This function:
// This changes resource.md output to write to /resource.html
eleventyConfig.addGlobalData("permalink", () => {
return (data) => ${data.page.filePathStem}.${data.page.outputFileExtension};
});
Maybe it has something to do. On the root level I am using {{post.url}} to loop through posts.md in the "blog' folder. This is outputting to It is the "/" before "blog" that must go.
Maybe there is something more I need in data, json files and front-matter. There must be some simple trick I'm missing. I will write a detailed description of my project. I am a student newbee with Eleventy. I still need help.
My project is at https://github.com/cwebba1/eleventyone
Hi Peter thank you for your reply and suggestion. I tried it but I could not get it to work. I tried with and without the "salmon" and other things as well.
Re: https://github.com/cwebba1/eleventyone/blob/73c9ccb0146ae317e61d550ff8672db193532466/app/_includes/article-snippet.njk#L5
I think if you're setting a pathPrefix you also need to use the url filter whenever outputting a [local] URL.
-<a href="{{post.url}}" class="btn btn--primary">Continue Reading</a>
+<a href="{{post.url | url}}" class="btn btn--primary">Continue Reading</a>
Not saying that will fix it, but is probably a good place to start debugging.
OK, I think I got this working after cloning your repo, but it wasn't as straight forward as I'd hoped.
I don't think pathPrefix is what you want since your use case seems to be variable nesting with root files and then blog/* files, so even if you have a pathPrefix of ../ it'll be wrong 50% of the time.
I ended up wrapping all the URLs w/ stuff like {{ root }}{{ '/index.html' | url }}.
But other times you need a slash between the {{ root }} and the path, like:
<img src="{{ root }}/{{ post.data.image | url }}" alt="{{ post.data.imageAlt }}" class="snippet__image">
Since that post.data.image is coming from the blog front matter, I'd probably just add a leading slash there to try and get this a bit more consistent.
Other places where you're using {{ page.url | url }} which is already prefixed with a /, it'd just be:
<a href="{{ root }}{{ post.url | url }}" class="btn btn--primary">Continue Reading</a>
And then the final pieces of the puzzle were tweaking the root variable in ./app/blog/blog.json to be:
{
"layout": "article.njk",
"tags": "post",
"root": ".."
}
And then setting a default root variable in .eleventy.js like this:
eleventyConfig.addGlobalData("root", () => ".");
(although, since your input files are already in a subdirectory, it might have been easier to set that in an ./app/app.json file) 🤷
Now when you're in the root ./index.html, it will look for assets relative to the current directory. But if you're in the ./blog/ folder, it will look one folder up, like:
<link rel="stylesheet" href="../css/style.css" />
Hi Peter deHaan,
Thank you for your help. I apologize for the slow response. I worked for three days over the 4th of July on this Eleventy project and I burned out.
I was able to use most of your suggestions. Now the website links are working.
Here is documentation for what I did:
I am following the Kevin Powell's "Turn static HTML/CSS into a blog with CMS using the JAMStack" tutorial https://www.youtube.com/watch?v=4wD00RT6d-g&t=1209s that is posted on YouTube.
However I am deviating from the tutorial in that I am altering the permalink function so that my Eleventy outputs pages with .html rather than folders containing index.html files.
On May 14th I got a tip from Bryan Robinson @brob https://twitter.com/brob and @eleven_ty https://twitter.com/eleven_ty how to change the permalink structure to do this. https://twitter.com/brob/status/1525521286314840065
// This changes resource.md output to write to /resource.html
eleventyConfig.addGlobalData("permalink", () => {
return (data) => `${data.page.filePathStem}.${data.page.outputFileExtension}`;
});
Why I landed on this page is that I needed to learn how to define and control relative paths in Eleventy. The navigation links were breaking in my output files.
– I removed pathPrefix as you suggested – I wrapped the top navigation links with {{ root }}{{ '/index.html' | url }} as you suggested. I tested with and without the {{ root }} and it is needed. It causes the nav links to add ../index.html to the navigation within the 2nd level blog folder and the same link outputs as index.html at the root folder level.
The {{ root }} is not needed on the blog links to articles. {{ post.url | url }} is enough. I searched for {{ root }} online and through eleventy and nunjucks documentation and I do not find it. Where did you learn about {{ root }}?
The {{ post.url | url }} appears in eleventy docs here, https://www.11ty.dev/docs/filters/url/#url-universal-filter but I did not understand it.
So to make this work I substituted Keven Powell's {{post.url}} for {{ post.url | url }}. It must be filtering? I'd like to understand more.
The root variable in ./app/blog/blog.json needed to stay as { "layout": "article.njk", "tags": "post", "root": "../" }
Removing the "/" causes the CSS to break.
Thank you again for your contribution and kindness. This is about learning how to implement and control relative paths in Eleventy. I am sure there will be more to learn.
"I searched for
{{ root }}online and through eleventy and nunjucks documentation and I do not find it. Where did you learn about{{ root }}?"
The {{ root }} thing isn't a Nunjucks or Eleventy thing, I just noticed it was being used in https://github.com/cwebba1/eleventyone/blob/73c9ccb0146ae317e61d550ff8672db193532466/app/blog/blog.json#L4 and tried to use the same logic.
Re: url filter, this part of the docs is most relevant:
"If you don’t need
pathPrefix(or don’t ever plan on moving your site’s top-level directory structure), you probably don’t need to use theurlfilter."
To be honest, I'm not sure I fully understand the thread or use case. I've rarely needed to use pathPrefix (unless I'm deploying to somewhere like GitHub Pages). Otherwise I just use the default behavior and use fully qualified paths like /foo/bar/index.html since I always know where my site will be deployed. I'm not sure how a site is being deployed that using either absolute paths or pathPrefix wouldn't work as expected, since having to manually figure out relative paths is tricky to do correctly 100% of the time.
The new HTML base plugin should handle this method fine. Although I would expect the url filter to handle it similarly. I don’t think setting pathPrefix to an empty string is what you want here.
With the default pathPrefix value ("/") Eleventy will not transform relative URLs.
{{ "/absolutePath/" | url }} => "/absolutePath/"
{{ "relativePath/" | url }} => "relativePath/"
If you change the pathPrefix to "/pathprefix/":
{{ "/absolutePath/" | url }} => "/pathprefix/absolutePath/"
{{ "relativePath/" | url }} => "relativePath/"
Keep in mind that pathPrefix is only used for URLs in your output—it has nothing to do with where the files go into your output folder on the file system.
It might be worth reviewing the new plugin docs, hopefully that will clarify things: https://www.11ty.dev/docs/plugins/html-base/
This is an automated message to let you know that a helpful response was posted to your issue and for the health of the repository issue tracker the issue will be closed. This is to help alleviate issues hanging open waiting for a response from the original poster.
If the response works to solve your problem—great! But if you’re still having problems, do not let the issue’s closing deter you if you have additional questions! Post another comment and we will reopen the issue. Thanks!