-
-
Notifications
You must be signed in to change notification settings - Fork 7.7k
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
Allow indexing of headings in Related #10711
Comments
I need to think about this for a bit, but before I do... Whatever we (meaning you) do here, can it "set the stage" to add headings to the content map at some point in the future? Primary use case: verify an anchor's existence in the link render hook. Every time a content author changes a heading, they run the risk of breaking links from other pages. It's easy to forget about the impact of changing a heading. The important bit is in the middle:
Again, I am not asking for this now. I just want to think forward a bit. Assuming it's even possible. |
If we did something like this at some point, I suggest:
The second one can be used to make sure the heading id's on a given page are unique. Or just do the second one... it's truthy/falsy. |
Yea, I have long wanted to create a map of the rendered content so you could create your own ToC etc. With that you could add methods ala As to this issue, I have amended the intro comment. |
OK, thinking about this a second time with my adjusted approach in mind:
What would be the use case of this? |
Verify an anchor's existence in the link render hook. Every time a content author changes a heading, they run the risk of breaking links from other pages. It's easy to forget about the impact of changing a heading. |
@jmooring OK, my first implementation of this has a One question for this particular Related feature:
|
Let's say that our And let's say that for Post 1 the How is that handled? Regarding naming... instead of changing the behavior (adding fragments) of I'm terrible with naming, but you get the idea. |
The best match, which I think is the only sensible behaviour.
Hmm ... Yea, I don't think the above would work, but it gave me an idea. I have always assumed that we somehow needed to make the fragments behave just like any other page, so you would not have to do anything special in the templates. But you could do:
|
Looks good to me. |
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. * When the match represents a Page fragment, then `.Fragment` will return non-nil. A short template example: ``` {{ $related := site.RegularPages.Related . }} {{ range $related }} {{ if .Fragment }} - {{ .Title }}: {{ .Fragment.Title }}: {{ .Fragment.RelPermalink }} {{ else }} - {{ .Title }}: {{ .RelPermalink }} {{ end }} {{ end }} ``` It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. * When the match represents a Page fragment, then `.Fragment` will return non-nil. A short template example: ``` {{ $related := site.RegularPages.Related . }} {{ range $related }} {{ if .Fragment }} - {{ .Title }}: {{ .Fragment.Title }}: {{ .Fragment.RelPermalink }} {{ else }} - {{ .Title }}: {{ .RelPermalink }} {{ end }} {{ end }} ``` It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
@jmooring OK, I have gone a few rounds with myself on this, and I think I now have a revised implementation that I'm reasonably happy with. I had a few wrong assumptions starting out with this:
With that I have added some new API that should make the ToC people happy, too. I have tested this briefly in the docs site: [related]
threshold = 20
includeNewer = true
toLower = false
[[related.indices]]
name = "keywords"
weight = 90
[[related.indices]]
name = "fragmentrefs"
type = "fragments"
applyFilter = true
weight = 70
[[related.indices]]
name = "date"
weight = 10
pattern = "2006" And the template: {{ $related := .Site.RegularPages.Related . | first 5 }}
{{ with $related }}
<h2>See Also</h2>
<ul>
{{ range . }}
<li>
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
{{ with .HeadingsFiltered }}
<ul>
{{ range . }}
{{ $link := printf "%s#%s" $.RelPermalink .ID }}
<li>
<a href="{{ $link }}">{{ .Title }}</a>
</li>
{{ end }}
</ul>
{{ end }}
</li>
{{ end }}
</ul>
{{ end }} Prints If I disable the filtering part I get: The other related new API on Page is:
// Fragments holds the table of contents for a page.
type Fragments struct {
// Headings holds the top level headings.
Headings Headings
// Identifiers holds all the identifiers in the ToC as a sorted slice.
// Note that collections.SortedStringSlice has both a Contains and Count method
// that can be used to identify missing and duplicate IDs.
Identifiers collections.SortedStringSlice
// HeadingsMap holds all the headings in the ToC as a map.
// Note that with duplicate IDs, the last one will win.
HeadingsMap map[string]*Heading
} You use the above to build your ToC etc. I will try to wrap this up later today, but shout if you disagree... |
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Adds two new methods to Page: Fragments (can also be used to build ToC) and HeadingsFiltered (this is only used in Related Content with index type `fragments` and `enableFilter` set to true. * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Adds two new methods to Page: Fragments (can also be used to build ToC) and HeadingsFiltered (this is only used in Related Content with index type `fragments` and `enableFilter` set to true. * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in gohugoio#9339. Closes gohugoio#10711 Updates gohugoio#9339 Updates gohugoio#10725
The main topic of this commit is that you can now index fragments (content heading identifiers) when calling `.Related`. You can do this by: * Configure one or more indices with type `fragments` * The name of those index configurations maps to an (optional) front matter slice with fragment references. This allows you to link page<->fragment and page<->page. * This also will index all the fragments (heading identifiers) of the pages. It's also possible to use type `fragments` indices in shortcode, e.g.: ``` {{ $related := site.RegularPages.Related .Page }} ``` But, and this is important, you need to include the shortcode using the `{{<` delimiter. Not doing so will create infinite loops and timeouts. This commit also: * Adds two new methods to Page: Fragments (can also be used to build ToC) and HeadingsFiltered (this is only used in Related Content with index type `fragments` and `enableFilter` set to true. * Consolidates all `.Related*` methods into one, which takes either a `Page` or an options map as its only argument. * Add `context.Context` to all of the content related Page API. Turns out it wasn't strictly needed for this particular feature, but it will soon become usefil, e.g. in #9339. Closes #10711 Updates #9339 Updates #10725
But only in the case where we know that we will need to access the Page fragments/tableofcontents. In normal situations this will spread naturally across the CPU cores, but not in the situation where `site.RegularPages.Related` gets called as part of e.g. the single template. ```bash name old time/op new time/op delta RelatedSite-10 18.0ms ± 2% 11.9ms ± 1% -34.17% (p=0.029 n=4+4) name old alloc/op new alloc/op delta RelatedSite-10 38.6MB ± 0% 38.6MB ± 0% ~ (p=0.114 n=4+4) name old allocs/op new allocs/op delta RelatedSite-10 117k ± 0% 117k ± 0% +0.23% (p=0.029 n=4+4) ``` See gohugoio#10711
But only in the case where we know that we will need to access the Page fragments/tableofcontents. In normal situations this will spread naturally across the CPU cores, but not in the situation where `site.RegularPages.Related` gets called as part of e.g. the single template. ```bash name old time/op new time/op delta RelatedSite-10 18.0ms ± 2% 11.9ms ± 1% -34.17% (p=0.029 n=4+4) name old alloc/op new alloc/op delta RelatedSite-10 38.6MB ± 0% 38.6MB ± 0% ~ (p=0.114 n=4+4) name old allocs/op new allocs/op delta RelatedSite-10 117k ± 0% 117k ± 0% +0.23% (p=0.029 n=4+4) ``` See gohugoio#10711
But only in the case where we know that we will need to access the Page fragments/tableofcontents. In normal situations this will spread naturally across the CPU cores, but not in the situation where `site.RegularPages.Related` gets called as part of e.g. the single template. ```bash name old time/op new time/op delta RelatedSite-10 18.0ms ± 2% 11.9ms ± 1% -34.17% (p=0.029 n=4+4) name old alloc/op new alloc/op delta RelatedSite-10 38.6MB ± 0% 38.6MB ± 0% ~ (p=0.114 n=4+4) name old allocs/op new allocs/op delta RelatedSite-10 117k ± 0% 117k ± 0% +0.23% (p=0.029 n=4+4) ``` See gohugoio#10711
But only in the case where we know that we will need to access the Page fragments/tableofcontents. In normal situations this will spread naturally across the CPU cores, but not in the situation where `site.RegularPages.Related` gets called as part of e.g. the single template. ```bash name old time/op new time/op delta RelatedSite-10 18.0ms ± 2% 11.9ms ± 1% -34.17% (p=0.029 n=4+4) name old alloc/op new alloc/op delta RelatedSite-10 38.6MB ± 0% 38.6MB ± 0% ~ (p=0.114 n=4+4) name old allocs/op new allocs/op delta RelatedSite-10 117k ± 0% 117k ± 0% +0.23% (p=0.029 n=4+4) ``` See gohugoio#10711
But only in the case where we know that we will need to access the Page fragments/tableofcontents. In normal situations this will spread naturally across the CPU cores, but not in the situation where `site.RegularPages.Related` gets called as part of e.g. the single template. ```bash name old time/op new time/op delta RelatedSite-10 18.0ms ± 2% 11.9ms ± 1% -34.17% (p=0.029 n=4+4) name old alloc/op new alloc/op delta RelatedSite-10 38.6MB ± 0% 38.6MB ± 0% ~ (p=0.114 n=4+4) name old allocs/op new allocs/op delta RelatedSite-10 117k ± 0% 117k ± 0% +0.23% (p=0.029 n=4+4) ``` See #10711
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
I'm in the process of reworking the reference section of the Hugo documentation. The general idea is:
reference
section is fully scripted (to put it simply) and describes every thing in Hugo (config option, function, method, ...) briefly.explanation
section (and some others) that explains the things in more detail. This section will be manually maintained.Related
indices (which comes on top of any manual linking).And the last bullet is the introduction to this issue. The Related Content feature works great for connecting pages on the top level, but does not handle anchor linking. And we have things in Hugo, e.g.
baseURL
, that isn't big enough to warrant its own page, at least not in the reference section.So, instead of trying to build a rubber bands and paper clips solution, I thought we could expand
Related
to support this.Edit: I have slept on this, and the catch 22 with my fist proposal above is obviously at we need to render the content before we can make the page selection. I have edited the below with a, I think, better way:
We adde a new
type
to therelated
config:Then, given the two Markdown documents:
The two pages should be linked correctly (the
see-also
shortcode is implied/custom, but the implementation should be trivial).And then when that heading match is included in a result set:
.RelPermalink
and.Permalink
will have the correct anchoring..Page.RelPermalink
will probably point to the page it wraps.There are some assumptions that may be clearer when we test this, but I think that all in all this should be both doable and relatively simple.
Assumptions:
Page
will be matched.@jmooring could this be a way to go? Any pitfalls or alternative approaches?
The text was updated successfully, but these errors were encountered: