gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
73.92k stars 7.41k forks source link

Hugo with uglyURLs = true generates /public/section.html instead of /public/section/index.html #4428

Open ChrisTucker2000 opened 6 years ago

ChrisTucker2000 commented 6 years ago

Discourse thread: https://discourse.gohugo.io/t/section-index-md-page-isnt-being-created/10627 Sample project: https://github.com/ChrisTucker2000/hugorepro

Steps to reproduce:

  1. Create a section index page, e.g. /content/cats/_index.md.
  2. Create an appropriate template file, e.g. /themes/mytheme/layouts/_default/list.html.
  3. Set uglyURLs = true in /config.toml.
  4. Build the website with hugo.

Expected result:

Actual result:

Additional information:

There is a Hugo documentation page discussing how uglyURLs works: https://gohugo.io/content-management/urls/#ugly-urls It clearly says on this page that /content/about/_index.md will map to https://example.com/about/ with uglyURLs = false and https://example.com/about/index.html with uglyURLs = true (so basically the same output file). This is the behavior that I expect, but it is not the behavior I'm getting.

Therefore this is either a bug in Hugo itself, or a mistake in the documentation. I hope it's the former, because this behavior seems totally bizarre and insane to me.

ChrisTucker2000 commented 6 years ago

Thanks. So it was a problem with the documentation then.

Is there any way to make Hugo generate the output that I expect though? I don't think I want anything unusual. In my opinion, most people would expect _index.md to map to index.html in the same folder, not sectionname.html in the parent directory. I could set up a post-build task to rename and move each file, but I'd prefer to have Hugo cooperate rather than having to fight against it.

Personally, I would rather Hugo be changed to generate this the way one would naturally expect (i.e. I'm making a feature request).

bep commented 6 years ago

Is there any way to make Hugo generate the output that I expect though?

You need to ask questions on the forum.

bep commented 6 years ago

I will reopen this as I agree this looks a little funky.

ChrisTucker2000 commented 6 years ago

I suppose this is off-topic, but I do wonder why do you seem to have this impatient, dismissive, almost hostile attitude towards people that criticism of Hugo. I ask this not just because of your attitude in this thread (closing the issue with no comment, and then simply redirecting me to Discourse with no feedback on my comments at the time), but also because I've seen a similar attitude from you while searching all over the internet trying to figure out how Hugo works due to the lack of clear documentation.

For example, in issue #4367 you just dismissed them, closed the bug report, and told them to go to Discourse. The person replied confirming their opinion that it was a bug in Hugo, with more details and a repro scenario included, but there's been no response for weeks and the issue is still closed. It honestly puts me off Hugo and makes it seem as though you refuse to engage in any feedback or discussion, but maybe I'm just overreacting and have only seen a few bad examples.

You said it yourself there that "We prefer to use GitHub issues only for bugs and enhancements". I'm making a feature request (enhancement). I literally said that in my previous message. And I already have a thread on Discourse - it's literally in the first line in the OP.


As for the "totally bizarre and insane" line, perhaps it's not very nice, but I don't think that makes it untrue. I apologise if any feelings were hurt. Of course you don't want to be made to feel like your work is unappreciated - but similarly people who take the time to give feedback don't want to feel like they're just being dismissed. I didn't see any code of conduct included for this repository, and other open source projects that I've been involved in have been accepting of such language, as what matters at the end of the day is listening to feedback (even if harsh) and improving the software.

From the perspective of somebody who previously produced websites manually without a static site generator such as Hugo, this behavior seems completely unexpected. Ordinarily, a website will be made up of regular files (e.g. about.html, contact.html) and each directory will have an index.html file as the default page for that directory. When moving to Hugo, I want to take the same approach and expect the same behavior. I expect to be able to create an index.md or _index.md file in a directory, to represent the content for its default page, and have that be generated as index.html. I would never in my wildest dreams expect it to generate a mysection.html file in the parent directory (i.e. a completely unrelated place). I put the file in the section directory for a reason. That's where I want the content to be. Not in the parent directory.

Perhaps it's because I don't quite understand Hugo's supposed "special handling" of index.md and _index.md files though. In my travels I've come to understand that Hugo was changed at some point, but the documentation seems to be lacking on it. I've seen the slogan "everything is a page now" but it doesn't seem like that to me as an end-user. If everything is just a simple page, then why can't I just have "index.md" which changes to "index.html" just like with every other page?

The way I see "uglyURLs" personally is that it should be "normalURLs". I don't expect anything to be ugly, I expect them to just be normal. I don't want Hugo to mess with my filenames or URLs. I just want file.md to translate to file.html. Personally, I think the default "pretty URLs" are actually quite ugly, littering the directory structure with hundreds of folders and creating index.html files everywhere. I think that most people would prefer to do URL rewriting on the web server with Apache .htaccess rules or Nginx configuration files. Maybe I'm just in a different world though.

My current workaround to this is to rename _index.md to _intro.md and set url = "sectionname/index.html" in the front matter, but it's a hack and I have to do it for every single section index page. I would prefer it if Hugo handled this better automatically.

Edit: I'm already running into issues with the above hacky workaround. While Hugo generates the section/index.html files that I want when using this hack, it still generates the original junk files, and furthermore the generated sitemap.xml file links to the junk files and makes no mention of the section/index.html files. This means I also have to run a custom post-build task to delete the junk files, and do a series of find+replace searches in sitemap.xml. Interestingly, the section/index.xml files do have the right links though.

onedrawingperday commented 6 years ago

@ChrisTucker2000 in case you don't know @bep is the lead dev for the Hugo project and he is working hard out of his own free time and pocket. So take it easy and show some respect.

Also long diatribes are difficult to read. Keep it short and to the point.

vinniejames commented 6 years ago

I somewhat agree with the request. While serving HTML from an Apache server (maybe others as well), without additional configuration the page is likely to return a 500 if a /folder and folder.html file share the same name

ratfactor commented 6 years ago

@ChrisTucker2000 and @vinniejames bring up some very valid technical challenges with the current "uglyURLs" behavior.

Perhaps a new setting could generate the output many of us are expecting:

public/<section>/index.html

...while not breaking existing sites which do depend on the current output:

public/<section>.html

Tongue-in-cheek, may I suggest a config property inspired by this conversation:

notBizarreAndInsaneURLs = true

:smile:

Seriously, though, the way the "Web works" since time immemorial has always been this sort of directory structure:

.
|-- stuff/
|    |-- foo1.html
|    |-- foo2.html
|    |-- foo3.html
|    `-- index.html           <--- the index for 'stuff/'!
|-- page1.html
|-- page2.html
|-- index.html                <--- the index for the site!

That's what web servers expect. That's what I expect. That's what works when serving a site from a filesystem without a web server. There's a reason it's called index.html!

Quite frankly, Hugo's current "ugly URL" behavior combined with the way it's named (undoubtedly meant in good humor) actually makes Hugo appear to consider this feature to be a "second class citizen" - that's unfriendly! Surely this is not what was intended.

Hugo is a wonderful application and I only wish to see it get better.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open. If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

ChrisTucker2000 commented 5 years ago

This is still important to me.

mpgirro commented 5 years ago

I would very much appreciate a configuration option for this issue too.

TjeuKayim commented 5 years ago

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

f00b4r0 commented 5 years ago

@bep

  • We cannot easily break existing behaviour, but if someone can prove that this has changed in some recent Hugo version, then we should fix it (I assume for both sections and taxonomy terms).

Hi, I stumbled upon this issue as I'm trying to upgrade from 0.21 (old, I know) to the most recent version (0.54 as of now) and it completely breaks my website.

Specifically, with 0.21 I used uglyURLs with the following architecture:

content/topic/index.md
content/topic/something.md
content/topic/someotherthing.md

and it would render like so

public/topic/index.html
public/topic/something.html
public/topic/someotherthing.html

Unfortunately with 0.54, having the index.md file in the topic directory makes hugo entirely ignore the other md files: it only renders public/topic/index.html and nothing else. And if I rename index.md to _index.md then I get:

public/topic.html
public/topic/something.html
public/topic/someotherthing.html

I did a manual 'binary search' in the releases, this bug/change has been introduced in 0.32. 0.31.1 behaves as I expect, 0.32 breaks my website.

HTH

infin80 commented 5 years ago

Does this put an end to this issue? https://gohugo.io/content-management/urls/#permalinks

thayerw commented 4 years ago

I'm so glad I stumbled onto this ticket, though I wish it were 12 hours earlier as I'm nearly bald from pulling my hair out :)

I would definitely like to see this resolved at some point. It goes against the expected behaviour of directory indexes and can break functionality when creating local directory-based websites.

thayerw commented 4 years ago

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

@TjeuKayim: Thank you so much!

For anyone else that find themselves here, TjeuKayim's workaround does work, though you will also need to define the layout (e.g. layout: section) in the front matter or it will likely render with the single.html template. Obviously this depends on your theme templates, but that seems to be the most common layout design.

s1-en commented 4 years ago

I spent so long trying to figure out why I can't get this to work atall until I found this issue thread. All the existing solutions provided have some kind of drawback in one way or another. I just wanted to have the list page show up in the section's folder as index.html :/

benolayinka commented 3 years ago

This is really unfortunate. It also breaks a website we're migrating from Jekyll, with lots of relative image urls which no longer work with /public/section.html instead of /public/section/index.html, since the directory changes.

benolayinka commented 3 years ago

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

But this solution breaks branch bundles -> https://gohugo.io/content-management/page-bundles/

vicmortelmans commented 2 years ago

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

I suppose the above is applied in combination with the config setting uglyURLs = true. But by doing so, it looks to me like you have the same result as with uglyURLs = false. Back to where you started, not?

I deploy the site on a local filesystem (file:///...) and links with trailing slash, like "<section>/" are not working. So I was using uglyURLs, but because the mismatch between "content/<section>/index.md" and "public/<section>.html", my relative image URLs were broken.

A better fix would be to stay with uglyURLs = false and to postprocess the files in public, modifying all @href links, adding index.html to the trailing slash:

"<section>/" ===> "<section>/index.html"

I wonder if that would be a viable concept for implementation in Hugo itself...

Best regards, Vic

gvegidy commented 2 years ago

A better fix would be to stay with uglyURLs = false and to postprocess the files in public, modifying all @href links, adding index.html to the trailing slash:

"<section>/" ===> "<section>/index.html"

I wonder if that would be a viable concept for implementation in Hugo itself...

Yes, something like that would be really helpful. For example as option indexHtmlURLs = true.

I want to use it to create a offline copy my website that is to be used from disk with file:// urls.

LunarWatcher commented 2 years ago

My hack is using url: /intro/ (in a file named /content/intro/_index.html; in general, just set the URL to be the desired path of the index file). Note that url: /intro/index.html does not work, and spews out XML instead, for some reason I do not understand. Like all other hacks, layout: single is also required

I couldn't for the life of me figure out where my index page went; it disappearing into intro.html didn't (and still doesn't) make any sense at all as a default.

domogami commented 1 year ago

A better fix would be to stay with uglyURLs = false and to postprocess the files in public, modifying all @href links, adding index.html to the trailing slash: "<section>/" ===> "<section>/index.html" I wonder if that would be a viable concept for implementation in Hugo itself...

Yes, something like that would be really helpful. For example as option indexHtmlURLs = true.

I want to use it to create a offline copy my website that is to be used from disk with file:// urls.

I would love to know if anything like this has been added because I am having the exact same problem and would love to convert <section>/ to <section>/index.html. For now I have resorted to manually changing the href links to include a hardcoded index.html. The service I am using to host wont render <section>/ links

sbootes commented 1 year ago

Even though this tread is closed, I have to say that as of 2022-10-06 nothing has changed. While ChrisTucker2000 may have used overly strong language, I have to agree with the issues he raised. As someone new to Hugo this month, I was about to abandon it altogether until I stumbled across this thread. I knew nothing about "ugly URLs" and coming from the Jekyll world I'm really struggling to understand Hugo. There's nothing intuitive about the system and while the documentation seems to be rigorous it isn't very unfriendly to novices. I hope something changes.

nairboon commented 1 year ago

This is still an issue as of v0.111.3

jmooring commented 1 year ago

This would be substantially addressed if https://github.com/gohugoio/hugo/pull/10847 is accepted/merged. When uglyURLs = true, you would have to do this for each top-level section:

[permalinks.section]
posts = "/:sections[0:]/index/"

Given this content:

content/
├── posts/
│   ├── foo/
│   │   ├── bar.md
│   │   └── _index.md
│   └── post-1.md
└── _index.md

The site would be published to:

public/
├── posts/
│   ├── foo/
│   │   ├── bar.html
│   │   └── index.html
│   ├── index.html
│   └── post-1.html
├── favicon.ico
└── index.html

And this approach is backwards compatible (we don't break anybody).

sbootes commented 1 year ago

Hi @jmooring,

Thanks for looking into this. I hope https://github.com/gohugoio/hugo/pull/10847 is accepted/merged. It will be a big help! :-)

Any idea if automatic menu generation will respect the permalink URL or require different syntax to make it work?

jmooring commented 1 year ago

@sbootes

automatic menu generation

Are you referring to the sectionPagesMenu configuration setting, or something else?

sbootes commented 1 year ago

@jmooring For automatic menu generation I was thinking of defining menu entries in the front matter of each page then accessing through site.menu.main. Please forgive the reference, but in Jekyl permalinks with an ugly URL are picked up automatically even when pages are nested. I realize Hugo will do nested menus but I haven't gotten it to generate menus for pages in in sub-directories yet. I just assumed that the problem was with the uglyURLs. My apologies if the question wasn't clear or is straying out of scope.

jmooring commented 1 year ago

@sbootes

I spoke too soon. We're publishing the pages in the right places, but the internal reference for section pages is broken. I can make it work with some trickery, but the section pages are then written with 2 dots before the extension (e.g., /posts/index..html). It works, but it's ugly.

I suspect this can be adjusted in https://github.com/gohugoio/hugo/pull/10847, but am reluctant to ask the PR author for additional work until we have an indication that the PR would be accepted.

For your other menu questions, please create a topic on the forum.

mmallet-digipok commented 11 months ago

I am happy to see I am not the only one struggling with uglyURLs. In my case, the hugo site is deployed in gitlab pages and the uglyURLs is required when using the gitlab pages preview feature, to see the site preview in mr/pr branch.

The root issue is on gitlab side as the preview implementation is hacky: the preview pages are not served the same way as the regular gitlab pages in gitlab and breaks the foo/bar/ to foo/bar/index.html redirections.

So I am indeed very interested is an option that works with uglyURLs and that would let me keep the html file name in the slug w/o changing the path.

I have /foo/bar/ directory that contains an _index.md file with its resources next to it (e.g. my-image.png referenced with « ./my-image.png » in markdown). When using uglyURLs, my links between pages are working but the page path and the image links become « /foo/bar.html » and « /foo/my-images.png » respectively, whereas the right image link should be « /foo/bar/my-images.png ».

I really hope it could be fixed :)

jmooring commented 11 months ago

@mmallet-digipok The problem you describe is about properly resolving a markdown image destination to a URL, best handled with render hooks. For example:

git clone --single-branch -b hugo-github-issue-4428 https://github.com/jmooring/hugo-testing hugo-github-issue-4428
cd hugo-github-issue-4428
hugo server

Properly resolving markdown image and link destinations, regardless of site structure or configuration, is not a trivial exercise.

mmallet-digipok commented 11 months ago

@mmallet-digipok The problem you describe is about properly resolving a markdown image destination to a URL, best handled with render hooks. For example:

git clone --single-branch -b hugo-github-issue-4428 https://github.com/jmooring/hugo-testing hugo-github-issue-4428
cd hugo-github-issue-4428
hugo server

Properly resolving markdown image and link destinations, regardless of site structure or configuration, is not a trivial exercise.

I agree that it is probably not trivial. I am rather frustrated that gitlab provided just one half of a feature ;)

I checked your code but I don't see why I would inject 500+ lines of code to fix something that has been working correctly with uglyURLs turned off (and that is natively handled by hugo. Anyway what @ChrisTucker2000 described is exactly the issue I'm facing.

mmallet-digipok commented 11 months ago

@jmooring your render-image hook has convinced me: it is working fine for me now, thank you! I just hope this piece of code will be somehow part of the hugo codebase.

jmooring commented 11 months ago

500+ lines of code

To clarify, the image render hook contains 73 lines of code. The link render hook contains 121 lines of code, but it does a lot a more, including the verification of URL fragments.

ytrepidorosonomous commented 7 months ago

This would be substantially addressed if #10847 is accepted/merged. When uglyURLs = true, you would have to do this for each top-level section:

[permalinks.section]
posts = "/:sections[0:]/index/"

Given this content:

content/
├── posts/
│   ├── foo/
│   │   ├── bar.md
│   │   └── _index.md
│   └── post-1.md
└── _index.md

The site would be published to:

public/
├── posts/
│   ├── foo/
│   │   ├── bar.html
│   │   └── index.html
│   ├── index.html
│   └── post-1.html
├── favicon.ico
└── index.html

And this approach is backwards compatible (we don't break anybody).

Was this addressed when the issue was merged? cc @jmooring

jmooring commented 7 months ago

@ashtallama No, as described above.

darksnow commented 3 weeks ago

I know this is an old thread but I wanted to add my voice to this. Hugo is a brilliant piece of software. I've used Jekyll and others in the past. The JS alternatives are too slow and for my uses I'm porting a previous small static site across to Hugo so I can then generate a lot of pages from a REST API. Hugo is the best solution for this I've found so far.

However, the sticking point seems so small that I'm surprised there's no solution, especially given the age of this thread.

If I have /content/section/_index.md and uglyURLs I'd expect the generated page to be at /section/index.html NOT section.html

This is a convention set down when Apache was the only real option and has been adopted by everyone since. Nginx does it, Caddy does it, even httpd does it. Hugo itself does this. This is well understood and is the expected behaviour that allows Hugo to do it's pretty URLs. A directory served by a web server should have an index.html page in it. The existing uglyURLs=false is an elegant use of this very behaviour that's expected everywhere.

There are numerous threads reporting this as an issue on here, all either brushed off or ignored. Numerous threads on the discussion board with much the same result. This is an often requested fix to a clear bug in how pages are generated.

I'd love to use Hugo, along with my existing Nginx setup to make pretty URLs. Can somebody please help me understand the reasoning behind this decision and why after it's being asked for for so long, it's been ignored?