Plan for namespacing template funcs

I’m working on hugo#3042 (PR here) and wanted to share a plan for which packages the existing funcs could be moved to. I’m soliciting feedback.

Before every freaks out and grabs their pitchforks, I’m not planning to deprecate all the functions you’re used to using. My goal is to move the Go code around into separate packages so that they’re easier to maintain while also remaining backwards compatible (at least for the foreseeable future).

  • Non-Namespace:
  • int
  • string
  • collections
  • after
  • apply
  • echoParam
  • delimit
  • dict
  • first
  • in
  • index
  • intersect
  • isset / isSet
  • last
  • seq
  • shuffle
  • slice
  • sort
  • union
  • where
  • compare
  • default
  • eq
  • ge
  • gt
  • le
  • lt
  • ne
  • crypto
  • md5
  • sha1
  • sha256
  • data
  • getCSV
  • getJSON
  • encoding
  • base64Decode
  • base64Encode
  • fmt (we already use the stdlib) :ballot_box_with_check:
  • print
  • printf
  • println
  • lang :question: (translation | translate)
  • i18n
  • T
  • image
  • imageConfig
  • inflect
  • humanize
  • pluralize
  • singularize
  • math
  • add
  • div
  • mod
  • modBool
  • mul
  • sub
  • os
  • getenv
  • readDir
  • readFile
  • safe
  • CSS
  • HTML
  • HTMLAttr
  • JS
  • JSStr
  • URL
  • sanitizeURL
  • sanitizeurl
  • strings
  • chomp
  • countrunes
  • countwords
  • findRE
  • hasPrefix
  • lower
  • replace
  • replaceRE
  • slicestr
  • split
  • substr
  • title
  • trim
  • truncate
  • upper
  • templates
  • partial
  • partialCached
  • time (conflicts with existing func name) :exclamation:
  • dateFormat
  • now
  • time :warning: Deprecate
  • transform
  • emojify
  • highlight
  • htmlEscape
  • htmlUnescape
  • jsonify
  • markdownify
  • plainify
  • queryify
  • urls
  • absURL
  • absLangURL
  • ref
  • relURL
  • relLangURL
  • relref
  • urlize

/cc @bep @digitalcraftsman @rdwatters

I will look closer later, it looks very very good in general. A few comments:

  • time: It is the obvious choice. Let us assume for argument’s sake that we pull this in after we release Hugo 0.20 (which I guess makes sense). Then we can do a “hard” deprecation of time (rename it) and just do the NS change for 0.21.
  • I’m not sure what you plan to do with the partial conflict, but I think maybe template would be a better package name?
  • net: I have no suggestion now, but it does not sound very good.
  • cast … hmm. Maybe.
  • Also, we need to do better than the base, i.e. many of these manipulate collections … It will end up as a basket to put stuff if we’re too lazy to think.
  • cast and transform sound very similar even if cast is mostly only used in the context of data types
  • lang seems to be a container for all i18n funcs. In the future we might add functions to format currencies, dates etc. Would you add them here, in transform or date?
  • net: getCSV and getJSON can load files from the local disk too and a network isn’t necessarily required. Maybe we could at least the current funcs with os
  • transform: see cast

Changes to OP:

  • base split into collections and operators (still need to decide on default func)
  • net changed to data
  • partial changed to templates
  • split func moved to strings

More options:

  • Rename cast to types?
  • Rename lang to translation or translate?

More questions:

  • time func moved to cast?

@bep, template is also an existing func name.

@digitalcraftsman, I meant for lang to include localization in the future. Does it make sense to split i18n and l10n into separate packages or can they coexist in the same package? Also, I was trying to avoid a naming conflict with the i18n func.

  1. No pitchfork here, and I’m with “not deprecating all the functions you’re used to using,” but per the question I asked you in the docs repo, is the long-term goal to change actual usage down the road for users (i.e., will these functions actually be called on the page with their respective ns)? Again, just for my own clarification, since both “yes” and “no” merit their own conversations.
  2. FYI, added to my TODO list.

You already changed this, but I’m just agreeing: cast vs transform may come off as a distinction without a difference to users (see my first question above).


So then time to types as well? If so, yes. If to cast, I think it makes more sense as a standalone but appreciate the conflict already mentioned twice here.

I was going to suggest data as well :thumbsup:

Hmmm… if not an accepted outlier, does it make sense to group under operators since it’s more like a single if/else statement than an actual ternary? I’m at a loss…

Any time you make things modular/organized/structured, you make this OCD person very happy :smile:

1 Like

Because they are closely related we could group them in the same namespace.

1 Like

Yes. Users will be able to use strings.Split in their templates.

does it make sense to group under operators since it’s more like a single if/else statement than an actual ternary?

I’m mulling it over. Thanks for the idea.

1 Like

The operators NS is closely related to the math NS and it’s name could imply the that it also contains operators like sub and mul. Alternatively, I would suggest comperators as an alternative.

1 Like

Yes and No.

  • For most new template funcs we should not create a short alias if it isn’t a new very fundamental func (not sure what the level of importance here is).
  • For the existing funcs, I suggest we let it evolve naturally in the versions after we do the namespacing.


  • We will never say range collections.Where in the funcs examples, me think …
  • We would also never say `strings.Print “something”```
  • But we might do, image.Convert (even if there is an imageConvert alias), because using the alias helps the user to understand there are other related funcs in that same namespace.
  • In my head, the first big win is to get some system in how we implement these funcs in the code. The added categories for the end user is a bonus.
1 Like

I agree. operators is too generic. They’re really comparison operators, always returning a bool, but they deal with more than just numerical comparisons.

I’ve renamed operators to compare.

1 Like