Pelican: `RELATIVE_URLS` and `SITEURL`

Created on 3 May 2015  路  11Comments  路  Source: getpelican/pelican

Please pardon my brashness as a newcomer here, but the RELATIVE_URLS + SITEURL behavior is broken, because it is being misused for several purposes. I see things like this scattered around templates:

 {{ SITEURL }}/{{ article.url }}

What you get out with RELATIVE_URLS = False is correct (e.g. http://example.com/blog/posts/2015/05/funfunfun/), but if RELATIVE_URLS = True, although it's technically correct, the instantiated template really goes all the way up the tree and then back down, e.g. you get things like ../../../../blog/posts/2015/05/funfunfun.

There are several requirements for URLs in a static site, and they are sometimes different even in the same site. RELATIVE_URLS affects _all_ instances of SITEURL. What is really needed is a per-use way of stating whether you want a relative or absolute URL from a given reference:

  • External scripts like Disqus comments need a full absolute URL. If the site in question is served via several DNS aliases (e.g. abcxyz.github.io and http://abcxyz.com and https://abcxyz.com) then this URL may need to be evaluated at runtime in Javascript to compute it properly.
  • Otherwise, relative URLs are good because they work even if there are several DNS aliases.
  • Then there are just the path portions of the URL. (absolute but without the protocol and domain name)

For example, suppose I am on a page http://abcxyz.com/blog/posts/123.html and I want a link to http://abcxyz.com/blog/themes/foobar.css. I can state this link as

  • ../themes/foobar.css (relative url)
  • http://abcxyz.com/blog/themes/foobar.css (full absolute url, breaks if served via multiple aliases)
  • /blog/themes/foobar.css (path portion of url)

I would much rather see a function provided to the jinja2 template than the use of {{SITEURL}}/{{someurl}}, in other words something like these:

{{ relative_url( someurl ) }}
{{ absolute_url( someurl ) }}
{{ url_path( someurl ) }}

This allows the choice to be made on a case-by-case basis at each point of use.

All 11 comments

I ended up using a workaround of this in my pelicanconf.py:

SITEURL = 'http://my.website.com'
SITEURL_ABS = SITEURL

and then using SITEURL_ABS in my theme when I need an absolute path, since it doesn't get touched by the URL relativizer the way SITEURL does.

Jinja functions might work for templates but that's not the whole story. There are also internal links in content. RELATIVE_URLS + SITEURL also affects those. How to handle them?

RELATIVE_URLS, right now, acts as a global switch. If you enable, you'll get relative urls everywhere except hardcoded urls (if you setup correctly).

Regarding your "workaround", I think that's a decent way of accomplishing what you want.

This is a problem for me too. I used the SITEURL_ABS solution, but it is a hack.

@avaris we could substitute new {absolute_ref} and {relative_ref} keywords to expand on existing behavior, and supply the new jinja functions.

might happen sometime in the future, but I think we have more urgent things in the queue

Same problem for me as well. My personal preference is using root-relative URLs wherever possible (and absolute otherwise, e.g. with feeds), but I suspect that another facet of the problem is that root-relative URLs don't reliably work for folks who don't use an HTTP server when developing locally.

+1 for interest, I think this issue urgently needs attention.

The situation is further confused for people like me who are sometimes looking to develop/preview locally (where the test server defaults to putting the entire site under "/" as the root URL) but for production want to deploy in such a way that the whole site will be hosted under "/foo". Shouldn't there be a separate concept of DOCUMENT_ROOT or something?

Regardless of whether different themes are using {{SITEURL}} everywhere they should, there's the separate matter of markdown links in content. The easiest thing to do to make links work everywhere as expected is to make the development setup more closely mirror the production one, so I think the test server also potentially needs to take into account SITEURL / RELATIVE_URLS / DOCUMENT_ROOT instead of always putting everything under "/".

I can volunteer time to make fixes and submit pull-requests.. but I think there needs to be some consensus about the approach first?

+1 needs fix

Since SITEURL gets tampered by Pelican during RELATIVE_URL, how about if we introduce ABSOLUTE_URL and just make a copy of SITEURL with it?

pelican already allows you to define custom variables (ALL_UPPERCASE) and use them in templates freely. So you can easily do:

SITEURL = 'whatever'
ABSOLUTE_URL = SITEURL

This is AWESOME! It works!

I did the following:

SITEURL = 'https://example.com/
ABSOLUTE_URL = SITEURL

and if pelicanconf.py has RELATIVE_URLS == True, then it becomes:

SITEURL = ..
ABSOLUTE_URL = 'https://example.com'

And if RELATIVE_URLS == False, then it becomes:

SITEURL = 'https://example.com'
ABSOLUTE_URL = 'https://example.com'

Perfect.

Given the workarounds listed here, as well as the already-existing ability to use distinct settings for local development and production (which are automatically generated by pelican-quickstart), I think this topic has been sufficiently addressed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kele14x picture kele14x  路  7Comments

Kristinita picture Kristinita  路  8Comments

jkarimi91 picture jkarimi91  路  6Comments

networkpadawan picture networkpadawan  路  3Comments

mwcz picture mwcz  路  5Comments