Optionally drop .html in links generated by url_for

Hi all,

I would like to have pretty URLs without enabling the directory_indexes feature, in order to avoid unnecessary redirections.

See for example GitHub pages which can already handle this out of the box: https://rsp.github.io/gh-pages-no-extension/

The problem is that url_for will currently output the full link including the html extension. Is it possible to optionally drop the .html extension in generated links ?



I don’t think that’s possible without using directory_indexes, no.

in order to avoid unnecessary redirections.

I’m not sure I follow. Once your site is built, how would using directory_indexes invoke unnecessary redirections?

I’m not sure I follow. Once your site is built, how would using directory_indexes invoke unnecessary redirections?

That’s the default behaviour for many web servers; if you request a URL such as e.g. /products which actually corresponds to a directory, the server will respond with a 301 redirect to /products/ (with a trailing slash added). Then the browser needs to make a second request to retrieve the actual page.

OK I have been able to remove the html extension from generated links by overriding the url_for helper as follows:

class RemoveHtml < Middleman::CoreExtensions::DefaultHelpers
  def initialize(app, options_hash={}, &block)

  helpers do
    def url_for(url, options_hash={})
      res = super(url, options_hash)

::Middleman::Extensions.register(:remove_html, RemoveHtml)
activate :remove_html

With this I can already generate the site in the way I need.

This breaks Middleman’s development server, which does not know it needs to add .html to URLs. This in turn can be fixed by using the “Optional Html” extension: Optional Html – an alternative to Directory Indexes for pretty URLs



I’m not sure this is true. It’s been a while so I could easily be wrong, but I believe most web servers will handle this without a redirect. When properly configured, I believe the webserver simply serves the index file when a directory path is provided without a specific html file.

Hi all and @guillerodriguez,

Your helper can now be vastly reduced to this, at least in Middleman 4.5:

helpers do
  def url_for(path_or_resource, options = {})
    super(path_or_resource, options).delete_suffix('.html')

Just add this to config.rb, in the helpers section. No need for all the extra declarations, Middleman is now taking care of it for you.

Cheers, François