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

Relative URLs to root of project #85

Closed
fserb opened this issue May 2, 2021 · 9 comments
Closed

Relative URLs to root of project #85

fserb opened this issue May 2, 2021 · 9 comments

Comments

@fserb
Copy link
Contributor

fserb commented May 2, 2021

I have a site (same data) that will be served from multiple locations. Therefore, it's not great to use absolute URLs there.

The problem is: I'm trying to generate a page data that points to the root, so I can, for example have a link pointing to: {{ root }}/assets/x.png that correctly resolves for all internal pages, no matter how deep their URLs is.

I was able to do something like this with:

site.data("rootPath", function() {
  return this.ctx.url.split('/').filter(x => x).map(_ => '..').join('/') || '.';
});

that mostly solves my problem but:

  1. I didn't see any documentation on this.ctx and I'm worried this will break in the future. Should we make site.data() callbacks receives a context?

  2. I know there's site.process plugins, but it would be great if there was a plugin mechanism to transform the data before rendering, so something like this could also be implemented.

@oscarotero
Copy link
Member

this.ctx does not exist in Lume. Where did you see it?

Lume has a url filter to generate urls including the domain or only the path. For example, with nunjucks, you could do:

<img href="{{ 'assets/x.png' | url }}">

@fserb
Copy link
Contributor Author

fserb commented May 2, 2021

url doesn't work for this case, because it assumes that it's being served on the root of the domain.

this.ctx comes from Nunjucks filters.

@oscarotero
Copy link
Member

url use the location configuration as base. If the location is, for example, https://mysite.com/subdirectory, the prefix /subdirectory is prepended to the returned path.

For example: <img src="{{ 'assets/x.png' | url }}"> returns <img src="/subdirectory/assets/x.png">.

Does it work for you?

@fserb
Copy link
Contributor Author

fserb commented May 2, 2021

Not really, I'd still have to do one build for each location. Maybe a relative_path or relative_url filter?

But mostly, how do you feel about a preprocess plugin entry that happens before rendering?

@oscarotero
Copy link
Member

Ok, got it.
Processors are executed after rendering. I think it's good because doing so, they are independent of the template engine used.

There is a inline processor here to inline automatically all css, javascript, images, etc, by searching in the html code all elements with the inline attribute.

I think we can do something similar for your use case, a processor to search all elements using an absolute path in the href/src attributes and convert them to relative. In fact, I have done something like that in another ssg I've created some years ago

@fserb
Copy link
Contributor Author

fserb commented May 2, 2021

Ahnnn. That could totally work. Good point.

I made a quick implementation of preprocess. But I'd defer to you if you think it's a good idea for this to exist at all.

@fserb
Copy link
Contributor Author

fserb commented May 2, 2021

Also, for future reference, here are the 3 implementations of rootPath that I ended up trying:

with a tag, abusing Nunchukjs. Use with {{ rootPath() }}/image.png:

site.data("rootPath", function() {
  return this.ctx.url.split('/').filter(x => x).map(_ => '..').join('/') || '.';
});

with a processor doing string substitution. Use with @ROOT@/image.png:

site.process([".njk", ".md", ".html"], (page) => {
  const root = page.data.url.split('/').filter(x => x).map(_ => '..').join('/') || '.';
  page.content = page.content.replaceAll("@ROOT@", root);
});

With a preprocessor (not supported). Use with {{ rootPath }}/image.png:

site.preprocess([".njk", ".md", ".html"], (page) => {
  page.data.rootPath = page.data.url.split('/').filter(x => x).map(_ => '..').join('/') || '.';
});

@oscarotero
Copy link
Member

I've created a plugin to convert all urls to relative: https://github.com/lumeland/lume/blob/master/plugins/relative_urls.js

You only have to import to your _config.js file:

import relative from "https://raw.githubusercontent.com/lumeland/lume/master/plugins/relative_urls.js";

site.use(relative())

I have tested it and seems to work fine. Could you check it?

@fserb
Copy link
Contributor Author

fserb commented May 2, 2021

It works perfectly. Thanks! :)

@fserb fserb closed this as completed May 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants