harttle / liquidjs

A simple, expressive, safe and Shopify compatible template engine in pure JavaScript.
https://liquidjs.com
MIT License
1.52k stars 238 forks source link

Feature: filter to add query string parameters #555

Closed amit777 closed 1 year ago

amit777 commented 1 year ago

It would be awesome to have a filter that could add parameters to a URL and automatically handle adding the ? to the URL if a parameter doesn't exist on the URL as well as overwrite the parameter if it already exists. Also handle hashes in the url as well.

eg

{{ "https://example.com" | append_query: "utm_source", "email" }}

output:

https://example.com?utm_source=email
pdehaan commented 1 year ago

@amit777 Maybe something like this?

const { Liquid } = require("liquidjs");

const engine = new Liquid();
engine.registerFilter('append_query', (url, name, value) => {
  const _url = new URL(url);
  _url.searchParams.append(name, value);
  return _url.href;
});

const tpl = engine.parse('{{ "https://example.com" | append_query: "utm_source", "email" }}');
engine.render(tpl)
  .then(console.log); // "https://example.com/?utm_source=email"

Or… possibly something like this if you want to pass multiple parameters (without chaining):

const { Liquid } = require("liquidjs");

const engine = new Liquid();
engine.registerFilter('append_query', (url, kv = {}) => {
  const _url = new URL(url);
  for (const [k, v] of Object.entries(kv)) {
    _url.searchParams.append(k, v);
  }
  return _url.href;
});

const args = {
  utm_source:"email",
  utm_name:"peter",
};
const tpl = engine.parseAndRender(`{{ "https://example.com/foo" | append_query: args }}`, {args})
  .then(console.log); // "https://example.com/foo?utm_source=email&utm_name=peter"
amit777 commented 1 year ago

Thanks! I'll give it a shot!

amit777 commented 1 year ago

works like a charm!

pdehaan commented 1 year ago

Another option I kind of like:

function (url, query="") {
    const _url = new URL(url);
    const _query = new URLSearchParams(query);
    for (const [k, v] of _query.entries()) {
      _url.searchParams.append(k, v);
    }
    return _url.href;
  }
{{ "https://example.com?name=peter" | append_query: "utm_source=email&foo=bar&name=paul" }}

OUTPUT

https://example.com/?name=peter&utm_source=email&foo=bar&name=paul

Feels a bit easier to chain multiple query params together without passing objects (and parsing as a URLSearchParams query string). Plus seems to append query params decently; although doesn't dedupe them as seen above.