Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected filter function naming #487

Closed
pdehaan opened this issue Mar 14, 2022 · 1 comment
Closed

Unexpected filter function naming #487

pdehaan opened this issue Mar 14, 2022 · 1 comment
Projects

Comments

@pdehaan
Copy link
Contributor

pdehaan commented Mar 14, 2022

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.

@harttle
Copy link
Owner

harttle commented Mar 15, 2022

Actually that's because liquid filter names are not always valid identifier (I mean default) in JavaScript. And this repo use snakeCase convention for variable naming.

Here's the 1:1 conversion from filter function name to template name:

export function snakeCase (str: string) {
return str.replace(
/(\w?)([A-Z])/g,
(_, a, b) => (a ? a + '_' : '') + b.toLowerCase()
)
}

@harttle harttle changed the title Unexpected filter naming in filters Unexpected filter function naming Mar 15, 2022
Repository owner locked and limited conversation to collaborators Mar 15, 2022
@harttle harttle converted this issue into discussion #488 Mar 15, 2022
@harttle harttle added this to To do in v10 Apr 21, 2022
@harttle harttle moved this from To do to In progress in v10 Nov 16, 2022
@harttle harttle moved this from In progress to Done in v10 Nov 16, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
No open projects
v10
Done
Development

No branches or pull requests

2 participants