shithub: hugo

Download patch

ref: 690b0f8ff5795318dfa3834a5a75d6623e7d934a
parent: e2b067f0504ba41ef45786e2f83d7002bd13a7eb
author: Bjørn Erik Pedersen <[email protected]>
date: Mon May 1 14:40:34 EDT 2017

tpl: Add docshelper for template funcs

And fix some other minor related issues.

Updates #3418

--- a/docs/data/docs.json
+++ b/docs/data/docs.json
@@ -258,5 +258,1228 @@
         ]
       }
     ]
+  },
+  "tpl": {
+    "funcs": [
+      {
+        "Name": "cast",
+        "Funcs": [
+          {
+            "Name": "ToInt",
+            "Description": "",
+            "Aliases": [
+              "int"
+            ],
+            "Examples": [
+              [
+                "{{ \"1234\" | int | printf \"%T\" }}",
+                "int"
+              ]
+            ]
+          },
+          {
+            "Name": "ToString",
+            "Description": "",
+            "Aliases": [
+              "string"
+            ],
+            "Examples": [
+              [
+                "{{ 1234 | string | printf \"%T\" }}",
+                "string"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "compare",
+        "Funcs": [
+          {
+            "Name": "Default",
+            "Description": "",
+            "Aliases": [
+              "default"
+            ],
+            "Examples": [
+              [
+                "{{ \"Hugo Rocks!\" | default \"Hugo Rules!\" }}",
+                "Hugo Rocks!"
+              ],
+              [
+                "{{ \"\" | default \"Hugo Rules!\" }}",
+                "Hugo Rules!"
+              ]
+            ]
+          },
+          {
+            "Name": "Eq",
+            "Description": "",
+            "Aliases": [
+              "eq"
+            ],
+            "Examples": [
+              [
+                "{{ if eq .Section \"blog\" }}current{{ end }}",
+                "current"
+              ]
+            ]
+          },
+          {
+            "Name": "Ge",
+            "Description": "",
+            "Aliases": [
+              "ge"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Gt",
+            "Description": "",
+            "Aliases": [
+              "gt"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Le",
+            "Description": "",
+            "Aliases": [
+              "le"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Lt",
+            "Description": "",
+            "Aliases": [
+              "lt"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Ne",
+            "Description": "",
+            "Aliases": [
+              "ne"
+            ],
+            "Examples": []
+          }
+        ]
+      },
+      {
+        "Name": "collections",
+        "Funcs": [
+          {
+            "Name": "After",
+            "Description": "",
+            "Aliases": [
+              "after"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Apply",
+            "Description": "",
+            "Aliases": [
+              "apply"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Delimit",
+            "Description": "",
+            "Aliases": [
+              "delimit"
+            ],
+            "Examples": [
+              [
+                "{{ delimit (slice \"A\" \"B\" \"C\") \", \" \" and \" }}",
+                "A, B and C"
+              ]
+            ]
+          },
+          {
+            "Name": "Dictionary",
+            "Description": "",
+            "Aliases": [
+              "dict"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "EchoParam",
+            "Description": "",
+            "Aliases": [
+              "echoParam"
+            ],
+            "Examples": [
+              [
+                "{{ echoParam .Params \"langCode\" }}",
+                "en"
+              ]
+            ]
+          },
+          {
+            "Name": "First",
+            "Description": "",
+            "Aliases": [
+              "first"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "In",
+            "Description": "",
+            "Aliases": [
+              "in"
+            ],
+            "Examples": [
+              [
+                "{{ if in \"this string contains a substring\" \"substring\" }}Substring found!{{ end }}",
+                "Substring found!"
+              ]
+            ]
+          },
+          {
+            "Name": "Index",
+            "Description": "",
+            "Aliases": [
+              "index"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Intersect",
+            "Description": "",
+            "Aliases": [
+              "intersect"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "IsSet",
+            "Description": "",
+            "Aliases": [
+              "isSet",
+              "isset"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Last",
+            "Description": "",
+            "Aliases": [
+              "last"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Querify",
+            "Description": "",
+            "Aliases": [
+              "querify"
+            ],
+            "Examples": [
+              [
+                "{{ (querify \"foo\" 1 \"bar\" 2 \"baz\" \"with spaces\" \"qux\" \"this\u0026that=those\") | safeHTML }}",
+                "bar=2\u0026baz=with+spaces\u0026foo=1\u0026qux=this%26that%3Dthose"
+              ],
+              [
+                "\u003ca href=\"https://www.google.com?{{ (querify \"q\" \"test\" \"page\" 3) | safeURL }}\"\u003eSearch\u003c/a\u003e",
+                "\u003ca href=\"https://www.google.com?page=3\u0026amp;q=test\"\u003eSearch\u003c/a\u003e"
+              ]
+            ]
+          },
+          {
+            "Name": "Seq",
+            "Description": "",
+            "Aliases": [
+              "seq"
+            ],
+            "Examples": [
+              [
+                "{{ seq 3 }}",
+                "[1 2 3]"
+              ]
+            ]
+          },
+          {
+            "Name": "Shuffle",
+            "Description": "",
+            "Aliases": [
+              "shuffle"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Slice",
+            "Description": "",
+            "Aliases": [
+              "slice"
+            ],
+            "Examples": [
+              [
+                "{{ slice \"B\" \"C\" \"A\" | sort }}",
+                "[A B C]"
+              ]
+            ]
+          },
+          {
+            "Name": "Sort",
+            "Description": "",
+            "Aliases": [
+              "sort"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Union",
+            "Description": "",
+            "Aliases": [
+              "union"
+            ],
+            "Examples": [
+              [
+                "{{ union (slice 1 2 3) (slice 3 4 5) }}",
+                "[1 2 3 4 5]"
+              ]
+            ]
+          },
+          {
+            "Name": "Where",
+            "Description": "",
+            "Aliases": [
+              "where"
+            ],
+            "Examples": []
+          }
+        ]
+      },
+      {
+        "Name": "crypto",
+        "Funcs": [
+          {
+            "Name": "MD5",
+            "Description": "",
+            "Aliases": [
+              "md5"
+            ],
+            "Examples": [
+              [
+                "{{ md5 \"Hello world, gophers!\" }}",
+                "b3029f756f98f79e7f1b7f1d1f0dd53b"
+              ],
+              [
+                "{{ crypto.MD5 \"Hello world, gophers!\" }}",
+                "b3029f756f98f79e7f1b7f1d1f0dd53b"
+              ]
+            ]
+          },
+          {
+            "Name": "SHA1",
+            "Description": "",
+            "Aliases": [
+              "sha1"
+            ],
+            "Examples": [
+              [
+                "{{ sha1 \"Hello world, gophers!\" }}",
+                "c8b5b0e33d408246e30f53e32b8f7627a7a649d4"
+              ]
+            ]
+          },
+          {
+            "Name": "SHA256",
+            "Description": "",
+            "Aliases": [
+              "sha256"
+            ],
+            "Examples": [
+              [
+                "{{ sha256 \"Hello world, gophers!\" }}",
+                "6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "data",
+        "Funcs": [
+          {
+            "Name": "GetCSV",
+            "Description": "",
+            "Aliases": [
+              "getCSV"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "GetJSON",
+            "Description": "",
+            "Aliases": [
+              "getJSON"
+            ],
+            "Examples": []
+          }
+        ]
+      },
+      {
+        "Name": "encoding",
+        "Funcs": [
+          {
+            "Name": "Base64Decode",
+            "Description": "",
+            "Aliases": [
+              "base64Decode"
+            ],
+            "Examples": [
+              [
+                "{{ \"SGVsbG8gd29ybGQ=\" | base64Decode }}",
+                "Hello world"
+              ],
+              [
+                "{{ 42 | base64Encode | base64Decode }}",
+                "42"
+              ]
+            ]
+          },
+          {
+            "Name": "Base64Encode",
+            "Description": "",
+            "Aliases": [
+              "base64Encode"
+            ],
+            "Examples": [
+              [
+                "{{ \"Hello world\" | base64Encode }}",
+                "SGVsbG8gd29ybGQ="
+              ]
+            ]
+          },
+          {
+            "Name": "Jsonify",
+            "Description": "",
+            "Aliases": [
+              "jsonify"
+            ],
+            "Examples": [
+              [
+                "{{ (slice \"A\" \"B\" \"C\") | jsonify }}",
+                "[\"A\",\"B\",\"C\"]"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "fmt",
+        "Funcs": [
+          {
+            "Name": "Print",
+            "Description": "",
+            "Aliases": [
+              "print"
+            ],
+            "Examples": [
+              [
+                "{{ print \"works!\" }}",
+                "works!"
+              ]
+            ]
+          },
+          {
+            "Name": "Printf",
+            "Description": "",
+            "Aliases": [
+              "printf"
+            ],
+            "Examples": [
+              [
+                "{{ printf \"%s!\" \"works\" }}",
+                "works!"
+              ]
+            ]
+          },
+          {
+            "Name": "Println",
+            "Description": "",
+            "Aliases": [
+              "println"
+            ],
+            "Examples": [
+              [
+                "{{ println \"works!\" }}",
+                "works!\n"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "images",
+        "Funcs": [
+          {
+            "Name": "Config",
+            "Description": "",
+            "Aliases": [
+              "imageConfig"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Lock",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "RLock",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "RLocker",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "RUnlock",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "Unlock",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          }
+        ]
+      },
+      {
+        "Name": "inflect",
+        "Funcs": [
+          {
+            "Name": "Humanize",
+            "Description": "",
+            "Aliases": [
+              "humanize"
+            ],
+            "Examples": [
+              [
+                "{{ humanize \"my-first-post\" }}",
+                "My first post"
+              ],
+              [
+                "{{ humanize \"myCamelPost\" }}",
+                "My camel post"
+              ],
+              [
+                "{{ humanize \"52\" }}",
+                "52nd"
+              ],
+              [
+                "{{ humanize 103 }}",
+                "103rd"
+              ]
+            ]
+          },
+          {
+            "Name": "Pluralize",
+            "Description": "",
+            "Aliases": [
+              "pluralize"
+            ],
+            "Examples": [
+              [
+                "{{ \"cat\" | pluralize }}",
+                "cats"
+              ]
+            ]
+          },
+          {
+            "Name": "Singularize",
+            "Description": "",
+            "Aliases": [
+              "singularize"
+            ],
+            "Examples": [
+              [
+                "{{ \"cats\" | singularize }}",
+                "cat"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "lang",
+        "Funcs": [
+          {
+            "Name": "Translate",
+            "Description": "",
+            "Aliases": [
+              "i18n",
+              "T"
+            ],
+            "Examples": []
+          }
+        ]
+      },
+      {
+        "Name": "math",
+        "Funcs": [
+          {
+            "Name": "Add",
+            "Description": "",
+            "Aliases": [
+              "add"
+            ],
+            "Examples": [
+              [
+                "{{add 1 2}}",
+                "3"
+              ]
+            ]
+          },
+          {
+            "Name": "Div",
+            "Description": "",
+            "Aliases": [
+              "div"
+            ],
+            "Examples": [
+              [
+                "{{div 6 3}}",
+                "2"
+              ]
+            ]
+          },
+          {
+            "Name": "Mod",
+            "Description": "",
+            "Aliases": [
+              "mod"
+            ],
+            "Examples": [
+              [
+                "{{mod 15 3}}",
+                "0"
+              ]
+            ]
+          },
+          {
+            "Name": "ModBool",
+            "Description": "",
+            "Aliases": [
+              "modBool"
+            ],
+            "Examples": [
+              [
+                "{{modBool 15 3}}",
+                "true"
+              ]
+            ]
+          },
+          {
+            "Name": "Mul",
+            "Description": "",
+            "Aliases": [
+              "mul"
+            ],
+            "Examples": [
+              [
+                "{{mul 2 3}}",
+                "6"
+              ]
+            ]
+          },
+          {
+            "Name": "Sub",
+            "Description": "",
+            "Aliases": [
+              "sub"
+            ],
+            "Examples": [
+              [
+                "{{sub 3 2}}",
+                "1"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "os",
+        "Funcs": [
+          {
+            "Name": "Getenv",
+            "Description": "",
+            "Aliases": [
+              "getenv"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "ReadDir",
+            "Description": "",
+            "Aliases": [
+              "readDir"
+            ],
+            "Examples": [
+              [
+                "{{ range (readDir \".\") }}{{ .Name }}{{ end }}",
+                "README.txt"
+              ]
+            ]
+          },
+          {
+            "Name": "ReadFile",
+            "Description": "",
+            "Aliases": [
+              "readFile"
+            ],
+            "Examples": [
+              [
+                "{{ readFile \"README.txt\" }}",
+                "Hugo Rocks!"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "partials",
+        "Funcs": [
+          {
+            "Name": "Include",
+            "Description": "",
+            "Aliases": [
+              "partial"
+            ],
+            "Examples": [
+              [
+                "{{ partial \"header.html\" . }}",
+                "\u003ctitle\u003eHugo Rocks!\u003c/title\u003e"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "safe",
+        "Funcs": [
+          {
+            "Name": "CSS",
+            "Description": "",
+            "Aliases": [
+              "safeCSS"
+            ],
+            "Examples": [
+              [
+                "{{ \"Bat\u0026Man\" | safeCSS | safeCSS }}",
+                "Bat\u0026amp;Man"
+              ]
+            ]
+          },
+          {
+            "Name": "HTML",
+            "Description": "",
+            "Aliases": [
+              "safeHTML"
+            ],
+            "Examples": [
+              [
+                "{{ \"Bat\u0026Man\" | safeHTML | safeHTML }}",
+                "Bat\u0026Man"
+              ],
+              [
+                "{{ \"Bat\u0026Man\" | safeHTML }}",
+                "Bat\u0026Man"
+              ]
+            ]
+          },
+          {
+            "Name": "HTMLAttr",
+            "Description": "",
+            "Aliases": [
+              "safeHTMLAttr"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "JS",
+            "Description": "",
+            "Aliases": [
+              "safeJS"
+            ],
+            "Examples": [
+              [
+                "{{ \"(1*2)\" | safeJS | safeJS }}",
+                "(1*2)"
+              ]
+            ]
+          },
+          {
+            "Name": "JSStr",
+            "Description": "",
+            "Aliases": [
+              "safeJSStr"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "SanitizeURL",
+            "Description": "",
+            "Aliases": [
+              "sanitizeURL",
+              "sanitizeurl"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "URL",
+            "Description": "",
+            "Aliases": [
+              "safeURL"
+            ],
+            "Examples": [
+              [
+                "{{ \"http://gohugo.io\" | safeURL | safeURL }}",
+                "http://gohugo.io"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "strings",
+        "Funcs": [
+          {
+            "Name": "Chomp",
+            "Description": "",
+            "Aliases": [
+              "chomp"
+            ],
+            "Examples": [
+              [
+                "{{chomp \"\u003cp\u003eBlockhead\u003c/p\u003e\\n\" }}",
+                "\u003cp\u003eBlockhead\u003c/p\u003e"
+              ]
+            ]
+          },
+          {
+            "Name": "Contains",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "ContainsAny",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "CountRunes",
+            "Description": "",
+            "Aliases": [
+              "countrunes"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "CountWords",
+            "Description": "",
+            "Aliases": [
+              "countwords"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "FindRE",
+            "Description": "",
+            "Aliases": [
+              "findRE"
+            ],
+            "Examples": [
+              [
+                "{{ findRE \"[G|g]o\" \"Hugo is a static side generator written in Go.\" \"1\" }}",
+                "[go]"
+              ]
+            ]
+          },
+          {
+            "Name": "HasPrefix",
+            "Description": "",
+            "Aliases": [
+              "hasPrefix"
+            ],
+            "Examples": [
+              [
+                "{{ hasPrefix \"Hugo\" \"Hu\" }}",
+                "true"
+              ],
+              [
+                "{{ hasPrefix \"Hugo\" \"Fu\" }}",
+                "false"
+              ]
+            ]
+          },
+          {
+            "Name": "HasSuffix",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "Replace",
+            "Description": "",
+            "Aliases": [
+              "replace"
+            ],
+            "Examples": [
+              [
+                "{{ replace \"Batman and Robin\" \"Robin\" \"Catwoman\" }}",
+                "Batman and Catwoman"
+              ]
+            ]
+          },
+          {
+            "Name": "ReplaceRE",
+            "Description": "",
+            "Aliases": [
+              "replaceRE"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "SliceString",
+            "Description": "",
+            "Aliases": [
+              "slicestr"
+            ],
+            "Examples": [
+              [
+                "{{slicestr \"BatMan\" 0 3}}",
+                "Bat"
+              ],
+              [
+                "{{slicestr \"BatMan\" 3}}",
+                "Man"
+              ]
+            ]
+          },
+          {
+            "Name": "Split",
+            "Description": "",
+            "Aliases": [
+              "split"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Substr",
+            "Description": "",
+            "Aliases": [
+              "substr"
+            ],
+            "Examples": [
+              [
+                "{{substr \"BatMan\" 0 -3}}",
+                "Bat"
+              ],
+              [
+                "{{substr \"BatMan\" 3 3}}",
+                "Man"
+              ]
+            ]
+          },
+          {
+            "Name": "Title",
+            "Description": "",
+            "Aliases": [
+              "title"
+            ],
+            "Examples": [
+              [
+                "{{title \"Bat man\"}}",
+                "Bat Man"
+              ]
+            ]
+          },
+          {
+            "Name": "ToLower",
+            "Description": "",
+            "Aliases": [
+              "lower"
+            ],
+            "Examples": [
+              [
+                "{{lower \"BatMan\"}}",
+                "batman"
+              ]
+            ]
+          },
+          {
+            "Name": "ToUpper",
+            "Description": "",
+            "Aliases": [
+              "upper"
+            ],
+            "Examples": [
+              [
+                "{{upper \"BatMan\"}}",
+                "BATMAN"
+              ]
+            ]
+          },
+          {
+            "Name": "Trim",
+            "Description": "",
+            "Aliases": [
+              "trim"
+            ],
+            "Examples": [
+              [
+                "{{ trim \"++Batman--\" \"+-\" }}",
+                "Batman"
+              ]
+            ]
+          },
+          {
+            "Name": "TrimPrefix",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "TrimSuffix",
+            "Description": "",
+            "Aliases": null,
+            "Examples": null
+          },
+          {
+            "Name": "Truncate",
+            "Description": "",
+            "Aliases": [
+              "truncate"
+            ],
+            "Examples": [
+              [
+                "{{ \"this is a very long text\" | truncate 10 \" ...\" }}",
+                "this is a ..."
+              ],
+              [
+                "{{ \"With [Markdown](/markdown) inside.\" | markdownify | truncate 14 }}",
+                "With \u003ca href=\"/markdown\"\u003eMarkdown …\u003c/a\u003e"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "time",
+        "Funcs": [
+          {
+            "Name": "AsTime",
+            "Description": "",
+            "Aliases": [
+              "asTime"
+            ],
+            "Examples": [
+              [
+                "{{ (asTime \"2015-01-21\").Year }}",
+                "2015"
+              ]
+            ]
+          },
+          {
+            "Name": "Format",
+            "Description": "",
+            "Aliases": [
+              "dateFormat"
+            ],
+            "Examples": [
+              [
+                "dateFormat: {{ dateFormat \"Monday, Jan 2, 2006\" \"2015-01-21\" }}",
+                "dateFormat: Wednesday, Jan 21, 2015"
+              ]
+            ]
+          },
+          {
+            "Name": "Now",
+            "Description": "",
+            "Aliases": [
+              "now"
+            ],
+            "Examples": []
+          }
+        ]
+      },
+      {
+        "Name": "transform",
+        "Funcs": [
+          {
+            "Name": "Emojify",
+            "Description": "",
+            "Aliases": [
+              "emojify"
+            ],
+            "Examples": [
+              [
+                "{{ \"I :heart: Hugo\" | emojify }}",
+                "I ❤️ Hugo"
+              ]
+            ]
+          },
+          {
+            "Name": "HTMLEscape",
+            "Description": "",
+            "Aliases": [
+              "htmlEscape"
+            ],
+            "Examples": [
+              [
+                "{{ htmlEscape \"Cathal Garvey \u0026 The Sunshine Band \[email protected]\u003e\" | safeHTML}}",
+                "Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;[email protected]\u0026gt;"
+              ],
+              [
+                "{{ htmlEscape \"Cathal Garvey \u0026 The Sunshine Band \[email protected]\u003e\"}}",
+                "Cathal Garvey \u0026amp;amp; The Sunshine Band \u0026amp;lt;[email protected]\u0026amp;gt;"
+              ],
+              [
+                "{{ htmlEscape \"Cathal Garvey \u0026 The Sunshine Band \[email protected]\u003e\" | htmlUnescape | safeHTML }}",
+                "Cathal Garvey \u0026 The Sunshine Band \[email protected]\u003e"
+              ]
+            ]
+          },
+          {
+            "Name": "HTMLUnescape",
+            "Description": "",
+            "Aliases": [
+              "htmlUnescape"
+            ],
+            "Examples": [
+              [
+                "{{ htmlUnescape \"Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;[email protected]\u0026gt;\" | safeHTML}}",
+                "Cathal Garvey \u0026 The Sunshine Band \[email protected]\u003e"
+              ],
+              [
+                "{{\"Cathal Garvey \u0026amp;amp; The Sunshine Band \u0026amp;lt;[email protected]\u0026amp;gt;\" | htmlUnescape | htmlUnescape | safeHTML}}",
+                "Cathal Garvey \u0026 The Sunshine Band \[email protected]\u003e"
+              ],
+              [
+                "{{\"Cathal Garvey \u0026amp;amp; The Sunshine Band \u0026amp;lt;[email protected]\u0026amp;gt;\" | htmlUnescape | htmlUnescape }}",
+                "Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;[email protected]\u0026gt;"
+              ],
+              [
+                "{{ htmlUnescape \"Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;[email protected]\u0026gt;\" | htmlEscape | safeHTML }}",
+                "Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;[email protected]\u0026gt;"
+              ]
+            ]
+          },
+          {
+            "Name": "Highlight",
+            "Description": "",
+            "Aliases": [
+              "highlight"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Markdownify",
+            "Description": "",
+            "Aliases": [
+              "markdownify"
+            ],
+            "Examples": [
+              [
+                "{{ .Title | markdownify}}",
+                "\u003cstrong\u003eBatMan\u003c/strong\u003e"
+              ]
+            ]
+          },
+          {
+            "Name": "Plainify",
+            "Description": "",
+            "Aliases": [
+              "plainify"
+            ],
+            "Examples": [
+              [
+                "{{ plainify  \"Hello \u003cstrong\u003eworld\u003c/strong\u003e, gophers!\" }}",
+                "Hello world, gophers!"
+              ]
+            ]
+          }
+        ]
+      },
+      {
+        "Name": "urls",
+        "Funcs": [
+          {
+            "Name": "AbsLangURL",
+            "Description": "",
+            "Aliases": [
+              "absLangURL"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "AbsURL",
+            "Description": "",
+            "Aliases": [
+              "absURL"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "Ref",
+            "Description": "",
+            "Aliases": [
+              "ref"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "RelLangURL",
+            "Description": "",
+            "Aliases": [
+              "relLangURL"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "RelRef",
+            "Description": "",
+            "Aliases": [
+              "relref"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "RelURL",
+            "Description": "",
+            "Aliases": [
+              "relURL"
+            ],
+            "Examples": []
+          },
+          {
+            "Name": "URLize",
+            "Description": "",
+            "Aliases": [
+              "urlize"
+            ],
+            "Examples": []
+          }
+        ]
+      }
+    ]
   }
 }
--- /dev/null
+++ b/tpl/cast/docshelper.go
@@ -1,0 +1,41 @@
+// Copyright 2017 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cast
+
+import (
+	"github.com/spf13/hugo/deps"
+	"github.com/spf13/hugo/docshelper"
+	"github.com/spf13/hugo/tpl/internal"
+)
+
+// This file provides documentation support and is randomly put into this package.
+func init() {
+	docsProvider := func() map[string]interface{} {
+		docs := make(map[string]interface{})
+		d := &deps.Deps{}
+
+		var namespaces []*internal.TemplateFuncsNamespace
+
+		for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
+			nf := nsf(d)
+			namespaces = append(namespaces, nf)
+
+		}
+
+		docs["funcs"] = namespaces
+		return docs
+	}
+
+	docshelper.AddDocProvider("tpl", docsProvider)
+}
--- a/tpl/cast/init.go
+++ b/tpl/cast/init.go
@@ -24,20 +24,26 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ "1234" | int | printf "%T" }}`, `int`},
-			{`{{ 1234 | string | printf "%T" }}`, `string`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"int":    ctx.ToInt,
-				"string": ctx.ToString,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.ToInt,
+			[]string{"int"},
+			[][2]string{
+				{`{{ "1234" | int | printf "%T" }}`, `int`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.ToString,
+			[]string{"string"},
+			[][2]string{
+				{`{{ 1234 | string | printf "%T" }}`, `string`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/collections/init.go
+++ b/tpl/collections/init.go
@@ -24,47 +24,121 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{`{{ delimit (slice "A" "B" "C") ", " " and " }}`, `A, B and C`},
-			{`{{ echoParam .Params "langCode" }}`, `en`},
-			{`{{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `Substring found!`},
-			{
-				`{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`,
-				`bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`},
-			{
-				`<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`,
-				`<a href="https://www.google.com?page=3&amp;q=test">Search</a>`},
-			{`{{ slice "B" "C" "A" | sort }}`, `[A B C]`},
-			{`{{ seq 3 }}`, `[1 2 3]`},
-			{`{{ union (slice 1 2 3) (slice 3 4 5) }}`, `[1 2 3 4 5]`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"after":     ctx.After,
-				"apply":     ctx.Apply,
-				"delimit":   ctx.Delimit,
-				"dict":      ctx.Dictionary,
-				"echoParam": ctx.EchoParam,
-				"first":     ctx.First,
-				"in":        ctx.In,
-				"index":     ctx.Index,
-				"intersect": ctx.Intersect,
-				"isSet":     ctx.IsSet,
-				"isset":     ctx.IsSet,
-				"last":      ctx.Last,
-				"querify":   ctx.Querify,
-				"shuffle":   ctx.Shuffle,
-				"slice":     ctx.Slice,
-				"sort":      ctx.Sort,
-				"union":     ctx.Union,
-				"where":     ctx.Where,
-				"seq":       ctx.Seq,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.After,
+			[]string{"after"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Apply,
+			[]string{"apply"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Delimit,
+			[]string{"delimit"},
+			[][2]string{
+				{`{{ delimit (slice "A" "B" "C") ", " " and " }}`, `A, B and C`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Dictionary,
+			[]string{"dict"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.EchoParam,
+			[]string{"echoParam"},
+			[][2]string{
+				{`{{ echoParam .Params "langCode" }}`, `en`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.First,
+			[]string{"first"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.In,
+			[]string{"in"},
+			[][2]string{
+				{`{{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `Substring found!`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Index,
+			[]string{"index"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Intersect,
+			[]string{"intersect"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.IsSet,
+			[]string{"isSet", "isset"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Last,
+			[]string{"last"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Querify,
+			[]string{"querify"},
+			[][2]string{
+				{
+					`{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`,
+					`bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`},
+				{
+					`<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`,
+					`<a href="https://www.google.com?page=3&amp;q=test">Search</a>`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Shuffle,
+			[]string{"shuffle"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Slice,
+			[]string{"slice"},
+			[][2]string{
+				{`{{ slice "B" "C" "A" | sort }}`, `[A B C]`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Sort,
+			[]string{"sort"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Union,
+			[]string{"union"},
+			[][2]string{
+				{`{{ union (slice 1 2 3) (slice 3 4 5) }}`, `[1 2 3 4 5]`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Where,
+			[]string{"where"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Seq,
+			[]string{"seq"},
+			[][2]string{
+				{`{{ seq 3 }}`, `[1 2 3]`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/compare/init.go
+++ b/tpl/compare/init.go
@@ -24,26 +24,52 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ if eq .Section "blog" }}current{{ end }}`, `current`},
-			{`{{ "Hugo Rocks!" | default "Hugo Rules!" }}`, `Hugo Rocks!`},
-			{`{{ "" | default "Hugo Rules!" }}`, `Hugo Rules!`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"default": ctx.Default,
-				"eq":      ctx.Eq,
-				"ge":      ctx.Ge,
-				"gt":      ctx.Gt,
-				"le":      ctx.Le,
-				"lt":      ctx.Lt,
-				"ne":      ctx.Ne,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Default,
+			[]string{"default"},
+			[][2]string{
+				{`{{ "Hugo Rocks!" | default "Hugo Rules!" }}`, `Hugo Rocks!`},
+				{`{{ "" | default "Hugo Rules!" }}`, `Hugo Rules!`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Eq,
+			[]string{"eq"},
+			[][2]string{
+				{`{{ if eq .Section "blog" }}current{{ end }}`, `current`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Ge,
+			[]string{"ge"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Gt,
+			[]string{"gt"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Le,
+			[]string{"le"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Lt,
+			[]string{"lt"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Ne,
+			[]string{"ne"},
+			[][2]string{},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/crypto/init.go
+++ b/tpl/crypto/init.go
@@ -24,23 +24,34 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ md5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`},
-			{`{{ crypto.MD5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`},
-			{`{{ sha1 "Hello world, gophers!" }}`, `c8b5b0e33d408246e30f53e32b8f7627a7a649d4`},
-			{`{{ sha256 "Hello world, gophers!" }}`, `6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"md5":    ctx.MD5,
-				"sha1":   ctx.SHA1,
-				"sha256": ctx.SHA256,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.MD5,
+			[]string{"md5"},
+			[][2]string{
+				{`{{ md5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`},
+				{`{{ crypto.MD5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.SHA1,
+			[]string{"sha1"},
+			[][2]string{
+				{`{{ sha1 "Hello world, gophers!" }}`, `c8b5b0e33d408246e30f53e32b8f7627a7a649d4`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.SHA256,
+			[]string{"sha256"},
+			[][2]string{
+				{`{{ sha256 "Hello world, gophers!" }}`, `6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/data/init.go
+++ b/tpl/data/init.go
@@ -24,19 +24,21 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"getCSV":  ctx.GetCSV,
-				"getJSON": ctx.GetJSON,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.GetCSV,
+			[]string{"getCSV"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.GetJSON,
+			[]string{"getJSON"},
+			[][2]string{},
+		)
+		return ns
 	}
 
 	internal.AddTemplateFuncsNamespace(f)
--- a/tpl/encoding/init.go
+++ b/tpl/encoding/init.go
@@ -24,23 +24,34 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ (slice "A" "B" "C") | jsonify }}`, `["A","B","C"]`},
-			{`{{ "SGVsbG8gd29ybGQ=" | base64Decode }}`, `Hello world`},
-			{`{{ 42 | base64Encode | base64Decode }}`, `42`},
-			{`{{ "Hello world" | base64Encode }}`, `SGVsbG8gd29ybGQ=`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"base64Decode": ctx.Base64Decode,
-				"base64Encode": ctx.Base64Encode,
-				"jsonify":      ctx.Jsonify,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Base64Decode,
+			[]string{"base64Decode"},
+			[][2]string{
+				{`{{ "SGVsbG8gd29ybGQ=" | base64Decode }}`, `Hello world`},
+				{`{{ 42 | base64Encode | base64Decode }}`, `42`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Base64Encode,
+			[]string{"base64Encode"},
+			[][2]string{
+				{`{{ "Hello world" | base64Encode }}`, `SGVsbG8gd29ybGQ=`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Jsonify,
+			[]string{"jsonify"},
+			[][2]string{
+				{`{{ (slice "A" "B" "C") | jsonify }}`, `["A","B","C"]`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/fmt/fmt.go
+++ b/tpl/fmt/fmt.go
@@ -26,14 +26,15 @@
 type Namespace struct {
 }
 
-func (ns *Namespace) Print(a ...interface{}) (n int, err error) {
-	return _fmt.Print(a...)
+func (ns *Namespace) Print(a ...interface{}) string {
+	return _fmt.Sprint(a...)
 }
 
-func (ns *Namespace) Printf(format string, a ...interface{}) (n int, err error) {
-	return _fmt.Printf(format, a...)
+func (ns *Namespace) Printf(format string, a ...interface{}) string {
+	return _fmt.Sprintf(format, a...)
+
 }
 
-func (ns *Namespace) Println(a ...interface{}) (n int, err error) {
-	return _fmt.Println(a...)
+func (ns *Namespace) Println(a ...interface{}) string {
+	return _fmt.Sprintln(a...)
 }
--- a/tpl/fmt/init.go
+++ b/tpl/fmt/init.go
@@ -24,18 +24,33 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ print "works!" }}`, `works!`},
-			{`{{ printf "%s!" "works" }}`, `works!`},
-			{`{{ println "works!" }}`, "works!\n"},
+		ns := &internal.TemplateFuncsNamespace{
+			Name:    name,
+			Context: func() interface{} { return ctx },
 		}
 
-		return &internal.TemplateFuncsNamespace{
-			Name:     name,
-			Context:  func() interface{} { return ctx },
-			Aliases:  map[string]interface{}{},
-			Examples: examples,
-		}
+		ns.AddMethodMapping(ctx.Print,
+			[]string{"print"},
+			[][2]string{
+				{`{{ print "works!" }}`, `works!`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Println,
+			[]string{"println"},
+			[][2]string{
+				{`{{ println "works!" }}`, "works!\n"},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Printf,
+			[]string{"printf"},
+			[][2]string{
+				{`{{ printf "%s!" "works" }}`, `works!`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/images/init.go
+++ b/tpl/images/init.go
@@ -24,18 +24,17 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"imageConfig": ctx.Config,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Config,
+			[]string{"imageConfig"},
+			[][2]string{},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/inflect/init.go
+++ b/tpl/inflect/init.go
@@ -24,25 +24,36 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ humanize "my-first-post" }}`, `My first post`},
-			{`{{ humanize "myCamelPost" }}`, `My camel post`},
-			{`{{ humanize "52" }}`, `52nd`},
-			{`{{ humanize 103 }}`, `103rd`},
-			{`{{ "cat" | pluralize }}`, `cats`},
-			{`{{ "cats" | singularize }}`, `cat`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"humanize":    ctx.Humanize,
-				"pluralize":   ctx.Pluralize,
-				"singularize": ctx.Singularize,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Humanize,
+			[]string{"humanize"},
+			[][2]string{
+				{`{{ humanize "my-first-post" }}`, `My first post`},
+				{`{{ humanize "myCamelPost" }}`, `My camel post`},
+				{`{{ humanize "52" }}`, `52nd`},
+				{`{{ humanize 103 }}`, `103rd`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Pluralize,
+			[]string{"pluralize"},
+			[][2]string{
+				{`{{ "cat" | pluralize }}`, `cats`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Singularize,
+			[]string{"singularize"},
+			[][2]string{
+				{`{{ "cats" | singularize }}`, `cat`},
+			},
+		)
+
+		return ns
 
 	}
 
--- /dev/null
+++ b/tpl/internal/templatefuncRegistry_test.go
@@ -1,0 +1,33 @@
+// Copyright 2017 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+type Test struct {
+}
+
+func (t *Test) MyTestMethod() string {
+	return "abcde"
+}
+
+func TestMethodToName(t *testing.T) {
+	test := &Test{}
+
+	require.Equal(t, "MyTestMethod", methodToName(test.MyTestMethod))
+}
--- a/tpl/internal/templatefuncsRegistry.go
+++ b/tpl/internal/templatefuncsRegistry.go
@@ -16,6 +16,12 @@
 package internal
 
 import (
+	"encoding/json"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+
 	"github.com/spf13/hugo/deps"
 )
 
@@ -32,12 +38,46 @@
 	// This is the method receiver.
 	Context interface{}
 
+	// Additional info, aliases and examples, per method name.
+	MethodMappings map[string]TemplateFuncMethodMapping
+}
+
+func (t *TemplateFuncsNamespace) AddMethodMapping(m interface{}, aliases []string, examples [][2]string) {
+	if t.MethodMappings == nil {
+		t.MethodMappings = make(map[string]TemplateFuncMethodMapping)
+	}
+
+	name := methodToName(m)
+
+	// sanity check
+	for _, e := range examples {
+		if e[0] == "" {
+			panic(t.Name + ": Empty example for " + name)
+		}
+	}
+	for _, a := range aliases {
+		if a == "" {
+			panic(t.Name + ": Empty alias for " + name)
+		}
+	}
+
+	t.MethodMappings[name] = TemplateFuncMethodMapping{
+		Method:   m,
+		Aliases:  aliases,
+		Examples: examples,
+	}
+
+}
+
+type TemplateFuncMethodMapping struct {
+	Method interface{}
+
 	// Any template funcs aliases. This is mainly motivated by keeping
 	// backwards compability, but some new template funcs may also make
 	// sense to give short and snappy aliases.
 	// Note that these aliases are global and will be merged, so the last
 	// key will win.
-	Aliases map[string]interface{}
+	Aliases []string
 
 	// A slice of input/expected examples.
 	// We keep it a the namespace level for now, but may find a way to keep track
@@ -44,4 +84,45 @@
 	// of the single template func, for documentation purposes.
 	// Some of these, hopefully just a few, may depend on some test data to run.
 	Examples [][2]string
+}
+
+func methodToName(m interface{}) string {
+	name := runtime.FuncForPC(reflect.ValueOf(m).Pointer()).Name()
+	name = filepath.Ext(name)
+	name = strings.TrimPrefix(name, ".")
+	name = strings.TrimSuffix(name, "-fm")
+	return name
+}
+
+func (t *TemplateFuncsNamespace) MarshalJSON() ([]byte, error) {
+	type Func struct {
+		Name        string
+		Description string // TODO(bep)
+		Aliases     []string
+		Examples    [][2]string
+	}
+	// TODO(bep) map/lookup from docs template Namespace + Func name.
+	var funcs []Func
+
+	ctx := t.Context.(func() interface{})()
+	ctxType := reflect.TypeOf(ctx)
+	for i := 0; i < ctxType.NumMethod(); i++ {
+		method := ctxType.Method(i)
+		f := Func{
+			Name: method.Name,
+		}
+		if mapping, ok := t.MethodMappings[method.Name]; ok {
+			f.Aliases = mapping.Aliases
+			f.Examples = mapping.Examples
+		}
+		funcs = append(funcs, f)
+	}
+
+	return json.Marshal(&struct {
+		Name  string
+		Funcs []Func
+	}{
+		Name:  t.Name,
+		Funcs: funcs,
+	})
 }
--- a/tpl/lang/init.go
+++ b/tpl/lang/init.go
@@ -24,19 +24,17 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"i18n": ctx.Translate,
-				"T":    ctx.Translate,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Translate,
+			[]string{"i18n", "T"},
+			[][2]string{},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/math/init.go
+++ b/tpl/math/init.go
@@ -24,28 +24,54 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{"{{add 1 2}}", "3"},
-			{"{{div 6 3}}", "2"},
-			{"{{mod 15 3}}", "0"},
-			{"{{modBool 15 3}}", "true"},
-			{"{{mul 2 3}}", "6"},
-			{"{{sub 3 2}}", "1"},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"add":     ctx.Add,
-				"div":     ctx.Div,
-				"mod":     ctx.Mod,
-				"modBool": ctx.ModBool,
-				"mul":     ctx.Mul,
-				"sub":     ctx.Sub,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Add,
+			[]string{"add"},
+			[][2]string{
+				{"{{add 1 2}}", "3"},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Div,
+			[]string{"div"},
+			[][2]string{
+				{"{{div 6 3}}", "2"},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Mod,
+			[]string{"mod"},
+			[][2]string{
+				{"{{mod 15 3}}", "0"},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.ModBool,
+			[]string{"modBool"},
+			[][2]string{
+				{"{{modBool 15 3}}", "true"},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Mul,
+			[]string{"mul"},
+			[][2]string{
+				{"{{mul 2 3}}", "6"},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Sub,
+			[]string{"sub"},
+			[][2]string{
+				{"{{sub 3 2}}", "1"},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/os/init.go
+++ b/tpl/os/init.go
@@ -24,21 +24,31 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{`{{ range (readDir ".") }}{{ .Name }}{{ end }}`, "README.txt"},
-			{`{{ readFile "README.txt" }}`, `Hugo Rocks!`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"getenv":   ctx.Getenv,
-				"readDir":  ctx.ReadDir,
-				"readFile": ctx.ReadFile,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Getenv,
+			[]string{"getenv"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.ReadDir,
+			[]string{"readDir"},
+			[][2]string{
+				{`{{ range (readDir ".") }}{{ .Name }}{{ end }}`, "README.txt"},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.ReadFile,
+			[]string{"readFile"},
+			[][2]string{
+				{`{{ readFile "README.txt" }}`, `Hugo Rocks!`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/partials/init.go
+++ b/tpl/partials/init.go
@@ -24,19 +24,24 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{`{{ partial "header.html" . }}`, `<title>Hugo Rocks!</title>`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"partial":       ctx.Include,
-				"partialCached": ctx.getCached,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Include,
+			[]string{"partial"},
+			[][2]string{
+				{`{{ partial "header.html" . }}`, `<title>Hugo Rocks!</title>`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.getCached,
+			[]string{"partialCached"},
+			[][2]string{},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/safe/init.go
+++ b/tpl/safe/init.go
@@ -24,29 +24,56 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ "Bat&Man" | safeCSS | safeCSS }}`, `Bat&amp;Man`},
-			{`{{ "Bat&Man" | safeHTML | safeHTML }}`, `Bat&Man`},
-			{`{{ "Bat&Man" | safeHTML }}`, `Bat&Man`},
-			{`{{ "(1*2)" | safeJS | safeJS }}`, `(1*2)`},
-			{`{{ "http://gohugo.io" | safeURL | safeURL }}`, `http://gohugo.io`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"safeCSS":      ctx.CSS,
-				"safeHTML":     ctx.HTML,
-				"safeHTMLAttr": ctx.HTMLAttr,
-				"safeJS":       ctx.JS,
-				"safeJSStr":    ctx.JSStr,
-				"safeURL":      ctx.URL,
-				"sanitizeURL":  ctx.SanitizeURL,
-				"sanitizeurl":  ctx.SanitizeURL,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.CSS,
+			[]string{"safeCSS"},
+			[][2]string{
+				{`{{ "Bat&Man" | safeCSS | safeCSS }}`, `Bat&amp;Man`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.HTML,
+			[]string{"safeHTML"},
+			[][2]string{
+				{`{{ "Bat&Man" | safeHTML | safeHTML }}`, `Bat&Man`},
+				{`{{ "Bat&Man" | safeHTML }}`, `Bat&Man`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.HTMLAttr,
+			[]string{"safeHTMLAttr"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.JS,
+			[]string{"safeJS"},
+			[][2]string{
+				{`{{ "(1*2)" | safeJS | safeJS }}`, `(1*2)`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.JSStr,
+			[]string{"safeJSStr"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.URL,
+			[]string{"safeURL"},
+			[][2]string{
+				{`{{ "http://gohugo.io" | safeURL | safeURL }}`, `http://gohugo.io`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.SanitizeURL,
+			[]string{"sanitizeURL", "sanitizeurl"},
+			[][2]string{},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/strings/init.go
+++ b/tpl/strings/init.go
@@ -24,53 +24,117 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{`{{chomp "<p>Blockhead</p>\n" }}`, `<p>Blockhead</p>`},
-			{
-				`{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." "1" }}`,
-				`[go]`},
-			{`{{ hasPrefix "Hugo" "Hu" }}`, `true`},
-			{`{{ hasPrefix "Hugo" "Fu" }}`, `false`},
-			{`{{lower "BatMan"}}`, `batman`},
-			{
-				`{{ replace "Batman and Robin" "Robin" "Catwoman" }}`,
-				`Batman and Catwoman`},
-			{
-				`{{ "http://gohugo.io/docs" | replaceRE "^https?://([^/]+).*" "$1" }}`,
-				`gohugo.io`},
-			{`{{slicestr "BatMan" 0 3}}`, `Bat`},
-			{`{{slicestr "BatMan" 3}}`, `Man`},
-			{`{{substr "BatMan" 0 -3}}`, `Bat`},
-			{`{{substr "BatMan" 3 3}}`, `Man`},
-			{`{{title "Bat man"}}`, `Bat Man`},
-			{`{{ trim "++Batman--" "+-" }}`, `Batman`},
-			{`{{ "this is a very long text" | truncate 10 " ..." }}`, `this is a ...`},
-			{`{{ "With [Markdown](/markdown) inside." | markdownify | truncate 14 }}`, `With <a href="/markdown">Markdown …</a>`},
-			{`{{upper "BatMan"}}`, `BATMAN`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"chomp":      ctx.Chomp,
-				"countrunes": ctx.CountRunes,
-				"countwords": ctx.CountWords,
-				"findRE":     ctx.FindRE,
-				"hasPrefix":  ctx.HasPrefix,
-				"lower":      ctx.ToLower,
-				"replace":    ctx.Replace,
-				"replaceRE":  ctx.ReplaceRE,
-				"slicestr":   ctx.SliceString,
-				"split":      ctx.Split,
-				"substr":     ctx.Substr,
-				"title":      ctx.Title,
-				"trim":       ctx.Trim,
-				"truncate":   ctx.Truncate,
-				"upper":      ctx.ToUpper,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Chomp,
+			[]string{"chomp"},
+			[][2]string{
+				{`{{chomp "<p>Blockhead</p>\n" }}`, `<p>Blockhead</p>`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.CountRunes,
+			[]string{"countrunes"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.CountWords,
+			[]string{"countwords"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.FindRE,
+			[]string{"findRE"},
+			[][2]string{
+				{
+					`{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." "1" }}`,
+					`[go]`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.HasPrefix,
+			[]string{"hasPrefix"},
+			[][2]string{
+				{`{{ hasPrefix "Hugo" "Hu" }}`, `true`},
+				{`{{ hasPrefix "Hugo" "Fu" }}`, `false`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.ToLower,
+			[]string{"lower"},
+			[][2]string{
+				{`{{lower "BatMan"}}`, `batman`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Replace,
+			[]string{"replace"},
+			[][2]string{
+				{
+					`{{ replace "Batman and Robin" "Robin" "Catwoman" }}`,
+					`Batman and Catwoman`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.ReplaceRE,
+			[]string{"replaceRE"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.SliceString,
+			[]string{"slicestr"},
+			[][2]string{
+				{`{{slicestr "BatMan" 0 3}}`, `Bat`},
+				{`{{slicestr "BatMan" 3}}`, `Man`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Split,
+			[]string{"split"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.Substr,
+			[]string{"substr"},
+			[][2]string{
+				{`{{substr "BatMan" 0 -3}}`, `Bat`},
+				{`{{substr "BatMan" 3 3}}`, `Man`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Trim,
+			[]string{"trim"},
+			[][2]string{
+				{`{{ trim "++Batman--" "+-" }}`, `Batman`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Title,
+			[]string{"title"},
+			[][2]string{
+				{`{{title "Bat man"}}`, `Bat Man`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Truncate,
+			[]string{"truncate"},
+			[][2]string{
+				{`{{ "this is a very long text" | truncate 10 " ..." }}`, `this is a ...`},
+				{`{{ "With [Markdown](/markdown) inside." | markdownify | truncate 14 }}`, `With <a href="/markdown">Markdown …</a>`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.ToUpper,
+			[]string{"upper"},
+			[][2]string{
+				{`{{upper "BatMan"}}`, `BATMAN`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/time/init.go
+++ b/tpl/time/init.go
@@ -24,21 +24,31 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New()
 
-		examples := [][2]string{
-			{`{{ (time "2015-01-21").Year }}`, `2015`},
-			{`dateFormat: {{ dateFormat "Monday, Jan 2, 2006" "2015-01-21" }}`, `dateFormat: Wednesday, Jan 21, 2015`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"dateFormat": ctx.Format,
-				"now":        ctx.Now,
-				"time":       ctx.AsTime,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Format,
+			[]string{"dateFormat"},
+			[][2]string{
+				{`dateFormat: {{ dateFormat "Monday, Jan 2, 2006" "2015-01-21" }}`, `dateFormat: Wednesday, Jan 21, 2015`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Now,
+			[]string{"now"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.AsTime,
+			[]string{"asTime"}, // TODO(bep) handle duplicate
+			[][2]string{
+				{`{{ (asTime "2015-01-21").Year }}`, `2015`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/tplimpl/template_funcs.go
+++ b/tpl/tplimpl/template_funcs.go
@@ -51,8 +51,14 @@
 			panic(ns.Name + " is a duplicate template func")
 		}
 		funcMap[ns.Name] = ns.Context
-		for k, v := range ns.Aliases {
-			funcMap[k] = v
+		for _, mm := range ns.MethodMappings {
+			for _, alias := range mm.Aliases {
+				if _, exists := funcMap[alias]; exists {
+					panic(alias + " is a duplicate template func")
+				}
+				funcMap[alias] = mm.Method
+			}
+
 		}
 	}
 
--- a/tpl/tplimpl/template_funcs_test.go
+++ b/tpl/tplimpl/template_funcs_test.go
@@ -87,19 +87,21 @@
 
 	for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
 		ns := nsf(d)
-		for i, example := range ns.Examples {
-			in, expected := example[0], example[1]
-			d.WithTemplate = func(templ tpl.TemplateHandler) error {
-				require.NoError(t, templ.AddTemplate("test", in))
-				require.NoError(t, templ.AddTemplate("partials/header.html", "<title>Hugo Rocks!</title>"))
-				return nil
-			}
-			require.NoError(t, d.LoadResources())
+		for _, mm := range ns.MethodMappings {
+			for i, example := range mm.Examples {
+				in, expected := example[0], example[1]
+				d.WithTemplate = func(templ tpl.TemplateHandler) error {
+					require.NoError(t, templ.AddTemplate("test", in))
+					require.NoError(t, templ.AddTemplate("partials/header.html", "<title>Hugo Rocks!</title>"))
+					return nil
+				}
+				require.NoError(t, d.LoadResources())
 
-			var b bytes.Buffer
-			require.NoError(t, d.Tmpl.Lookup("test").Execute(&b, &data))
-			if b.String() != expected {
-				t.Fatalf("%s[%d]: got %q expected %q", ns.Name, i, b.String(), expected)
+				var b bytes.Buffer
+				require.NoError(t, d.Tmpl.Lookup("test").Execute(&b, &data))
+				if b.String() != expected {
+					t.Fatalf("%s[%d]: got %q expected %q", ns.Name, i, b.String(), expected)
+				}
 			}
 		}
 	}
--- a/tpl/transform/init.go
+++ b/tpl/transform/init.go
@@ -24,46 +24,71 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{`{{ "I :heart: Hugo" | emojify }}`, `I ❤️ Hugo`},
-			{`{{ .Title | markdownify}}`, `<strong>BatMan</strong>`},
-			{`{{ plainify  "Hello <strong>world</strong>, gophers!" }}`, `Hello world, gophers!`},
-			{
-				`htmlEscape 1: {{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | safeHTML}}`,
-				`htmlEscape 1: Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`},
-			{
-				`htmlEscape 2: {{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>"}}`,
-				`htmlEscape 2: Cathal Garvey &amp;amp; The Sunshine Band &amp;lt;[email protected]&amp;gt;`},
-			{
-				`htmlUnescape 1: {{htmlUnescape "Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | safeHTML}}`,
-				`htmlUnescape 1: Cathal Garvey & The Sunshine Band <[email protected]>`},
-			{
-				`htmlUnescape 2: {{"Cathal Garvey &amp;amp; The Sunshine Band &amp;lt;[email protected]&amp;gt;" | htmlUnescape | htmlUnescape | safeHTML}}`,
-				`htmlUnescape 2: Cathal Garvey & The Sunshine Band <[email protected]>`},
-			{
-				`htmlUnescape 3: {{"Cathal Garvey &amp;amp; The Sunshine Band &amp;lt;[email protected]&amp;gt;" | htmlUnescape | htmlUnescape }}`,
-				`htmlUnescape 3: Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`},
-			{
-				`htmlUnescape 4: {{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | htmlUnescape | safeHTML }}`,
-				`htmlUnescape 4: Cathal Garvey & The Sunshine Band <[email protected]>`},
-			{
-				`htmlUnescape 5: {{ htmlUnescape "Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | htmlEscape | safeHTML }}`,
-				`htmlUnescape 5: Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"emojify":      ctx.Emojify,
-				"highlight":    ctx.Highlight,
-				"htmlEscape":   ctx.HTMLEscape,
-				"htmlUnescape": ctx.HTMLUnescape,
-				"markdownify":  ctx.Markdownify,
-				"plainify":     ctx.Plainify,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.Emojify,
+			[]string{"emojify"},
+			[][2]string{
+				{`{{ "I :heart: Hugo" | emojify }}`, `I ❤️ Hugo`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Highlight,
+			[]string{"highlight"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.HTMLEscape,
+			[]string{"htmlEscape"},
+			[][2]string{
+				{
+					`{{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | safeHTML}}`,
+					`Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`},
+				{
+					`{{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>"}}`,
+					`Cathal Garvey &amp;amp; The Sunshine Band &amp;lt;[email protected]&amp;gt;`},
+				{
+					`{{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | htmlUnescape | safeHTML }}`,
+					`Cathal Garvey & The Sunshine Band <[email protected]>`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.HTMLUnescape,
+			[]string{"htmlUnescape"},
+			[][2]string{
+				{
+					`{{ htmlUnescape "Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | safeHTML}}`,
+					`Cathal Garvey & The Sunshine Band <[email protected]>`},
+				{
+					`{{"Cathal Garvey &amp;amp; The Sunshine Band &amp;lt;[email protected]&amp;gt;" | htmlUnescape | htmlUnescape | safeHTML}}`,
+					`Cathal Garvey & The Sunshine Band <[email protected]>`},
+				{
+					`{{"Cathal Garvey &amp;amp; The Sunshine Band &amp;lt;[email protected]&amp;gt;" | htmlUnescape | htmlUnescape }}`,
+					`Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`},
+				{
+					`{{ htmlUnescape "Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | htmlEscape | safeHTML }}`,
+					`Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Markdownify,
+			[]string{"markdownify"},
+			[][2]string{
+				{`{{ .Title | markdownify}}`, `<strong>BatMan</strong>`},
+			},
+		)
+
+		ns.AddMethodMapping(ctx.Plainify,
+			[]string{"plainify"},
+			[][2]string{
+				{`{{ plainify  "Hello <strong>world</strong>, gophers!" }}`, `Hello world, gophers!`},
+			},
+		)
+
+		return ns
 
 	}
 
--- a/tpl/urls/init.go
+++ b/tpl/urls/init.go
@@ -24,32 +24,42 @@
 	f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
 		ctx := New(d)
 
-		examples := [][2]string{
-			{`{{ "index.html" | absLangURL }}`, `http://mysite.com/hugo/en/index.html`},
-			{`{{ "http://gohugo.io/" | absURL }}`, `http://gohugo.io/`},
-			{`{{ "mystyle.css" | absURL }}`, `http://mysite.com/hugo/mystyle.css`},
-			{`{{ 42 | absURL }}`, `http://mysite.com/hugo/42`},
-			{`{{ "index.html" | relLangURL }}`, `/hugo/en/index.html`},
-			{`{{ "http://gohugo.io/" | relURL }}`, `http://gohugo.io/`},
-			{`{{ "mystyle.css" | relURL }}`, `/hugo/mystyle.css`},
-			{`{{ mul 2 21 | relURL }}`, `/hugo/42`},
-			{`{{ "Bat Man" | urlize }}`, `bat-man`},
-		}
-
-		return &internal.TemplateFuncsNamespace{
+		ns := &internal.TemplateFuncsNamespace{
 			Name:    name,
 			Context: func() interface{} { return ctx },
-			Aliases: map[string]interface{}{
-				"absURL":     ctx.AbsURL,
-				"absLangURL": ctx.AbsLangURL,
-				"ref":        ctx.Ref,
-				"relURL":     ctx.RelURL,
-				"relLangURL": ctx.RelLangURL,
-				"relref":     ctx.RelRef,
-				"urlize":     ctx.URLize,
-			},
-			Examples: examples,
 		}
+
+		ns.AddMethodMapping(ctx.AbsURL,
+			[]string{"absURL"},
+			[][2]string{},
+		)
+
+		ns.AddMethodMapping(ctx.AbsLangURL,
+			[]string{"absLangURL"},
+			[][2]string{},
+		)
+		ns.AddMethodMapping(ctx.Ref,
+			[]string{"ref"},
+			[][2]string{},
+		)
+		ns.AddMethodMapping(ctx.RelURL,
+			[]string{"relURL"},
+			[][2]string{},
+		)
+		ns.AddMethodMapping(ctx.RelLangURL,
+			[]string{"relLangURL"},
+			[][2]string{},
+		)
+		ns.AddMethodMapping(ctx.RelRef,
+			[]string{"relref"},
+			[][2]string{},
+		)
+		ns.AddMethodMapping(ctx.URLize,
+			[]string{"urlize"},
+			[][2]string{},
+		)
+
+		return ns
 
 	}