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
Enable descriptive header IDs. #591
Conversation
This is a great change. Thanks! It's failing the ci because there's a few tests that check to make sure the output matches and are looking for "toc". Can you look into that before I merge this? |
Certainly. Should I try to put this behaviour behind a flag, or do we accept that this is a breaking change, otherwise? (It’ll affect the tests—and probably a number of bits in the documentation, it looks like.) |
I'm fine with the breaking change. I can't imagine anyone ever would prefer the prior behavior. |
Then, I’ve also fixed the TOC extraction as well. I’m going to merge all of these fixes into a single commit and adjust the description. |
As a side note, this does introduce a small problem on list pages, because all markdown headers that are rendered on the list page will have IDs, and if there are headers that have the same text, multiple headers will result in the same ID. |
Duplicate ids on a page is no-go, in my eyes (and many will shout louder). But there must be a way around it? BTW, I really like the Blackfriday patches you are pulling out of your sleeve. |
The duplicate IDs problem is going to be hard to solve, because Blackfriday doesn’t really keep any tabs on separate renderings. That is, I could produce a further patch to Blackfriday that would do the right thing given: # My Heading
# My Heading Such that it would be In other words, it’s doable, but it has just gone from nice to ugly. We could go a bit further with Hugo and add a functions to help: I can see the value of {{ $ref := .Get "ref" }}
{{ $title := .Get "title" }}
{{ $inner := .Inner }}
{{ range first 1 (where .Page.Node.Site.Pages "Name" $ref) }}
{{ if len $title }}
<a href="{{ .Permalink }}">{{ $title }}</a>
{{ else }}
{{ if len $inner }}
<a href="{{ .Permalink }}">{{ $inner }}</a>
{{ else }}
<a href="{{ .Permalink }}">{{ .Title }}</a>
{{ end }}
{{ end }}
{{ end }} I can see about working up a patch to blackfriday that covers the duplicated header in a single file issue—that shouldn’t be too hard (it means maintaining a bit of extra state, but nothing fancy). I’m a bit less sanguine about adding a prefix or suffix for header generation, although that wouldn’t be too hard, either. My problem with that is what it ends up doing to the Hugo interface. |
I see your points and troubles; I guess this is a problem best solved with a good night sleep :-) |
@bjornerik Any thoughts on how we should resolve this? I’m going to work on a blackfriday patch to fix the in-document duplicate problem, but the cross-document duplicate is 100% a Hugo problem that will require assistance from blackfriday to solve. I don’t think that the cross-document issue a big deal, to be honest, because:
|
@halostatue One thought I had was the possibility to remove the ids on the list pages? The problem isn't really the TOC on the list pages, but the duplicate HTML identities. The browers are fine about it (I guess), but validation purists will be annoyed when "half" of their pages go red in the validator. |
I haven’t gotten deep enough into Hugo’s rendering code to know how well it knows the difference between list and single rendering to know whether it could do this. @spf13, do you know whether this is the case? (We could probably get away with it for Browsers are fine about it—people write bad HTML all the time, and they still mostly work. The behaviour in a browser, as far as I can tell, is to ignore the existence of all duplicate IDs after the first. |
Again, I believe most validators will complain. |
I’m not disagreeing with you; I’m just saying that browsers have to deal with that all the time because of hand-written HTML and bad tutorials. You’re more likely to run into problems with jQuery & the like because of this. I’m certain that I can strip out header IDs if I know that it’s a list context. |
With respect to the first issue, I have opened russross/blackfriday#126 with one implementation and a suggestion for another implementation that I consider problematic (I’ve explained in the commit and pull-request). I’m leaning toward your suggestion of stripping any IDs in |
I really love this functionality, but also agree with the points made here on both sides. I'm going to wait to merge this until we've solved the duplicate ID issue. That can be in this PR or in another, but I think we should wait for that fix before adding this. |
@halostatue Hugo isn't setup to handle things very differently between the list and single renderings. I think this is best implemented with a post rendering filter (but I could be wrong). |
So… something like |
I was thinking more like a transformer... see https://github.com/spf13/hugo/tree/master/transform An example of one is https://github.com/spf13/hugo/blob/master/transform/livereloadinject.go That said, I haven't thought through it very much, but I think it would probably be the best place for it. The transform subsystem was designed for post processing actions like this. One issue there though is that they operate on all posts, not just a set of them. I was thinking of it being an automatic thing where it checks to see for duplicate Ids and appends something to the dupes.... perhaps the post title for instance. While the stripHeaderIds as a template filter has some merit, I typically avoid any option which requires user action without decision. In this case 100% of users want to avoid duplicate ids. There isn't a decision to make so we shouldn't require them to do something. I also think it's an obscure enough thing that most won't take the time to learn about it. Another idea is that for all listings we append the post title to the ids... not sure where we would implement that though. |
A list’s top-level As I said in russross/blackfriday#126, I think that the naive per-page approach in blackfriday is probably sufficient (most markdown documents are fairly short and unique). If we spat out a warning if we recognized a duplicate header (perhaps by reading the TOC) on a page, we might be able to even not need the naive per-page approach added in the blackfriday PR. In Hugo, we only need to really worry about multiple-document single-rendering duplication (e.g., a Hugo list context), and that’s maybe the point of the transform you’ve suggested, where we either strip the IDs (which I think is more useful in a list context) or we modify the IDs to include the (As an aside, I have an idea for putting the TOC into a |
@halostatue Where does this PR stand? |
Pretty much where it stood before. I want to try to push forward, but I don't know how to fix the duplicate ID problem (and I haven't moved on the blackfriday PR, either). I’ll probably have time to look at it next week during RubyConf. |
@halostatue you will have plenty of time waiting for the gems to download :-) |
I’ve got a writeup on my blog. Basically:
It’s imperfect, but I don’t really see a better way to do it. |
Enable blackfriday.EXTENSION_AUTO_HEADER_IDS to generate the name of the header ID from the text in the header. Works for prefix and underline headers. - TOC extraction had to be modified to look for `<li><a href="#`> instead of `#toc_` because of this change. - Fixed a number of tests that depended on the presence of `toc_` with as an `id` or as a `href` value. - Renames the earlier parameter `footnoteref` to `documentId` as it more accurately represents the nature of the parameter. The `documentId` is appended to all generated headers through the new HTML renderer parameter `HeaderIDSuffix`.
|
Note that this will now fail builds until russross/blackfriday is updated with my two pending PRs. |
These were merged. @spf13, can you kick build 765 on Travis to rebuild? |
Merged as 8f9cea7 |
Awesome, thanks. I am finishing the last part, which is .Rel and .RelRef with equivalent shortcodes. @bjornerik, this requires some tweaking of your wrapper code because of where the |
@halostatue no problem - looks like I'll have to wait for the REAL Black Friday before I'll get to do stuff with that one. |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Enable blackfriday.EXTENSION_AUTO_HEADER_IDS to generate the name of the header ID from the text in the header. Works for prefix and underline headers.
WARNING: This change is not backwards-compatible, so it should probably be put under a configuration option. That is, the existing behaviour of Hugo is to use #toc__n_ for header IDs. Now, a header will match its contents.
Under the old model, that would generate:
Under the new model, that will generate:
The automatically generated TOC will use the correct values regardless, but it may be advisable to explicitly specify the old #toc__n_ model as part of the header:
Or, we make a larger change that checks for this particular flag being enabled through a configuration option, defaulting to on. (Older blogs will need to make one change to their
config.*
file to maintain the current behaviour, and it could also potentially be on a per-page basis. Maybe.)