Split any string to a specified number of words

Here is a technique that I use to split a string and output a specified number of words.

Full code:

{{- $caption := $.Site.Params.caption -}}
{{- $caption = split .node.text " " -}}
{{- range first 22 $caption -}}{{- . }} {{ end -}}
{{- range first 1 (after 22 $caption) -}}{{- . -}}{{- end -}}…{{- end -}}

The above can be adapted anyway one needs also it can be used to generated custom post summaries provided that the post content is sanitized beforehand with the plainify function to remove any HTML.

Step-by-step explanation

The text in this example is provided by a .Params.caption in the project’s config.

{{ $caption := $.Site.Params.caption }}
{{ $caption = split .node.text " " }}

Use the split function to convert the string into substrings, (the delimiter is the space between the words i.e. " ").

{{ range first 22 $caption }}

range through the substrings and enter the desired number of words.

{{ . }} {{ end }}

Note the space between {{ . }} and {{ end }}, it is required because otherwise the words will be printed consecutively.

{{ range first 1 (after 22 $caption) }}
{{ . }}{{ end }}…{{ end }}

For the last word I do not need a following space but an ellipsis.

That’s all.


Note that there is also

Implemented by the CEO of Netlify.


truncate is indeed a simplification.

For example the above technique can be condensed into:

{{ $caption := .Site.Params.caption | truncate 145 }}{{ $caption }}{{ end }}

However, truncate does not suit my needs.

truncate outputs: blahablah ...
meanwhile the technique with split above outputs: blahablah...

The space that is rendered between the last word and the ellipsis with truncate is undesirable for me
(I am aware that one could use regEx to eliminate that space, but that is a bit of an overkill).

It’s all a matter of style preference.


FYI, the truncate function allows you to supply the ellipse string to use. The default is a space preceding an ellipse, but you could pass in one without a space. or three emoji if you wanted. From the function docs:

truncate SIZE INPUT

Thank you for pointing that out. I didn’t notice.