[SOLVED] Filter pages based on shortcode

Hi! I’ve made a deprecated shortcode that allows me to put a notice when a page is out of date. Its body has some Markdown explaining why the page is out of date, maybe where to look instead, etc.

Now I’d like to filter any pages using this shortcode out of indexes and the like. Can anyone suggest a way to do that? One additional criteria: it needs to work with the Paginate method.

where won’t work since AFAIK it can’t call methods like HasShortcode.

I would love to do something like setting Params.deprecated to true in, say, _baseof.html, but I don’t think you can set Params from a template?

I tried to instead .Scratch.Set "deprecated" true in _baseof, but then I have no way to fetch it with where.

I also tried to just assemble an array of pages in a loop in a template, but Paginate appears to really want some kind of special collection of pages and not just an array (error calling Paginate: unsupported type in paginate, got []interface {}).

I could, of course, just set a front matter variable, but then I have to set the front matter variable and also call the shortcode from the page body. This seems like needless duplication, though—HasShortcode knows if I’ve used the deprecated shortcode on the page!—and also error-prone, since I could easily forget to add the variable, or remove the deprecated shortcode but forget to remove the variable as well.


You’re missing the context. You need the dollar sign $ to go higher up from within the shortcode.

You can call it by using .Scratch.Get. Please see the Docs about .Scratch they’ve been recently updated.

Thanks for the reply! Could you be more specific about this part, please? As far as I know I can’t do something like where .Pages "Scratch.Get \"deprecated\"" "!=" true, right?

Hang on a minute. I misread your post. You do not need to use .Scratch for that.

You set the deprecated parameter in the front matter of the content files and then you call it like so:

{{ range where .Site.RegularPages ".Params.deprecate" "eq" true -}} 

That true is a boolean literal BTW.

Also since you want to filter pages by a Param you need to do that from a partial within your templates.

A shortcode goes in the body of a content file and usually it adds an extra something to that page, you cannot use shortcodes to filter pages in lists.

I think this is the key sentence for me. :slight_smile: As a programmer I see this nice HasShortcode method over here, and this nice where function over there, and naturally I want to put them together. This is probably yet another battle in the “how much code in templates is too much code in templates” war.

FWIW, here’s how I’m going to get around this:

{{ $allPages := where .Pages.ByLastmod.Reverse "Section" "posts" }}
{{ $.Scratch.Set "deprecatedPages" (slice) }}
{{ range $allPages }}
	{{ if .HasShortcode "deprecated" }}
    	{{ $.Scratch.Add "deprecatedPages" .UniqueID }}
	{{ end }}
{{ end }}
{{ $paginator := .Paginate (where $allPages "UniqueID" "not in" ($.Scratch.Get "deprecatedPages")) }}

If I could either mutate Page.Params, or get values out of Scratch using the dotted syntax, I could just use where. I know, PRs welcome!