Skip to content

Unexpected filter function naming #487

Closed
@pdehaan

Description

@pdehaan

I was trying to see if I could use LiquidJS filters outside of .liquid templates (well, shimming them into Nunjucks templates using Eleventy, as a proof of concept), but this caught me a bit by surprise:

const liquidVersion = require("liquidjs/package.json").version;
const filters = require("liquidjs").filters;

console.log(JSON.stringify({
  filters: Object.keys(filters).sort(),
  liquidVersion
}, null, 2));

OUTPUT

{
  "filters": [
    "Default",
    "abs",
    "append",
    "atLeast",
    "atMost",
    "capitalize",
    "ceil",
    "compact",
    "concat",
    "date",
    "dividedBy",
    "downcase",
    "escape",
    "escapeOnce",
    "first",
    "floor",
    "join",
    "json",
    "last",
    "lstrip",
    "map",
    "minus",
    "modulo",
    "newlineToBr",
    "plus",
    "prepend",
    "remove",
    "removeFirst",
    "replace",
    "replaceFirst",
    "reverse",
    "round",
    "rstrip",
    "size",
    "slice",
    "sort",
    "sortNatural",
    "split",
    "strip",
    "stripHtml",
    "stripNewlines",
    "times",
    "truncate",
    "truncatewords",
    "uniq",
    "upcase",
    "urlDecode",
    "urlEncode",
    "where"
  ],
  "liquidVersion": "9.36.0"
}

What was a bit surprising is that I got an object back with urlDecode instead of the actual filter name, url_decode. Attempting to use some of of these mixed case filters unsurprisingly throws errors:

[11ty] > undefined filter: stripHtml

So if I'm trying to manually add these filters into Nunjucks templates, I either have to name each one with the underscore variant, or else slugify the provided filter names myself using something like @sindresorhus/slugify with a custom separator:

const slugify = require("@sindresorhus/slugify");
const liquidFilters = require("liquidjs").filters;

for (const name of Object.keys(liquidFilters).sort()) {
  console.log(`${name}:\t${slugify(name, {separator:"_"})}`);
}

OUTPUT

require("liquidjs").filters NAME SLUGIFIED NAME
Default default
abs abs
append append
atLeast at_least
atMost at_most
capitalize capitalize
ceil ceil
compact compact
concat concat
date date
dividedBy divided_by
downcase downcase
escape escape
escapeOnce escape_once
first first
floor floor
join join
json json
last last
lstrip lstrip
map map
minus minus
modulo modulo
newlineToBr newline_to_br
plus plus
prepend prepend
remove remove
removeFirst remove_first
replace replace
replaceFirst replace_first
reverse reverse
round round
rstrip rstrip
size size
slice slice
sort sort
sortNatural sort_natural
split split
strip strip
stripHtml strip_html
stripNewlines strip_newlines
times times
truncate truncate
truncatewords truncatewords
uniq uniq
upcase upcase
urlDecode url_decode
urlEncode url_encode
where where

EXPECTED RESULTS

console.log(require("liquidjs").filters);

[Object: null prototype] {
   escape: [Function: escape],
-  escapeOnce: [Function: escapeOnce],
+  escape_once: [Function: escapeOnce],
-  newlineToBr: [Function: newlineToBr],
+  newline_to_br: [Function: newlineToBr],
-  stripHtml: [Function: stripHtml],
+  strip_html: [Function: stripHtml],
   abs: [Function (anonymous)],
-  atLeast: [Function (anonymous)],
+  at_least: [Function (anonymous)],
-  atMost: [Function (anonymous)],
+  at_most: [Function (anonymous)],
   ceil: [Function (anonymous)],
-  dividedBy: [Function (anonymous)],
+  divided_by: [Function (anonymous)],
   floor: [Function (anonymous)],
   minus: [Function (anonymous)],
   modulo: [Function (anonymous)],
   times: [Function (anonymous)],
   round: [Function: round],
   plus: [Function: plus],
-  urlDecode: [Function: urlDecode],
+  url_decode: [Function urlDecode],
-  urlEncode: [Function: urlEncode],
+  url_encode: [Function: urlEncode],
   join: [Function (anonymous)],
   last: [Function (anonymous)],
   first: [Function (anonymous)],
   reverse: [Function (anonymous)],
   sort: [Function: sort],
-  sortNatural: [Function: sortNatural],
+  sort_natural: [Function: sortNatural],
   size: [Function: size],
   map: [Function: map],
   compact: [Function: compact],
   concat: [Function: concat],
   slice: [Function: slice],
   where: [Function: where],
   uniq: [Function: uniq],
   date: [Function: date],
-  Default: [Function: Default],
+  default: [Function: Default],
   json: [Function: json],
   append: [Function: append],
   prepend: [Function: prepend],
   lstrip: [Function: lstrip],
   downcase: [Function: downcase],
   upcase: [Function: upcase],
   remove: [Function: remove],
-  removeFirst: [Function: removeFirst],
+  remove_first: [Function: removeFirst],
   rstrip: [Function: rstrip],
   split: [Function: split],
   strip: [Function: strip],
-  stripNewlines: [Function: stripNewlines],
+  strip_newlines: [Function: stripNewlines],
   capitalize: [Function: capitalize],
   replace: [Function: replace],
-  replaceFirst: [Function: replaceFirst],
+  replace_first: [Function: replaceFirst],
   truncate: [Function: truncate],
   truncatewords: [Function: truncatewords]
}

Feel free to close this. I know it's a pretty bizarre edge case, but thought it might be worth documenting here, and fixing it is possibly a breaking change in case somebody is already relying on the current.stripNewlines vs proposed strip_newlines object key naming.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions