Files
liquidjs/docs/source/tutorials/parse-parameters.md
T
a0ea372764 docs: fix some spelling (#708)
* spelling: according

Signed-off-by: Josh Soref <[email protected]>

* spelling: asynchronously

Signed-off-by: Josh Soref <[email protected]>

* spelling: background

Signed-off-by: Josh Soref <[email protected]>

* spelling: camel

Signed-off-by: Josh Soref <[email protected]>

* spelling: cannot

Signed-off-by: Josh Soref <[email protected]>

* spelling: case-sensitive

Signed-off-by: Josh Soref <[email protected]>

* spelling: comparison

Signed-off-by: Josh Soref <[email protected]>

* spelling: demos

Signed-off-by: Josh Soref <[email protected]>

* spelling: forloop

Signed-off-by: Josh Soref <[email protected]>

* spelling: formatters

Signed-off-by: Josh Soref <[email protected]>

* spelling: github

Signed-off-by: Josh Soref <[email protected]>

* spelling: guidelines

Signed-off-by: Josh Soref <[email protected]>

* spelling: hashes

Signed-off-by: Josh Soref <[email protected]>

* spelling: https

Signed-off-by: Josh Soref <[email protected]>

* spelling: javascript

Signed-off-by: Josh Soref <[email protected]>

* spelling: keep

Signed-off-by: Josh Soref <[email protected]>

* spelling: natural

Signed-off-by: Josh Soref <[email protected]>

* spelling: neither

Signed-off-by: Josh Soref <[email protected]>

* spelling: no longer

Signed-off-by: Josh Soref <[email protected]>

* spelling: nonexistent

Signed-off-by: Josh Soref <[email protected]>

* spelling: output

Signed-off-by: Josh Soref <[email protected]>

* spelling: polymorphism

Signed-off-by: Josh Soref <[email protected]>

* spelling: precache

Signed-off-by: Josh Soref <[email protected]>

* spelling: programmatically

Signed-off-by: Josh Soref <[email protected]>

* spelling: punctuation

Signed-off-by: Josh Soref <[email protected]>

* spelling: registration

Signed-off-by: Josh Soref <[email protected]>

* spelling: rendered

Signed-off-by: Josh Soref <[email protected]>

* spelling: synchronously

Signed-off-by: Josh Soref <[email protected]>

* spelling: thrown

Signed-off-by: Josh Soref <[email protected]>

* spelling: trimmed

Signed-off-by: Josh Soref <[email protected]>

* spelling: unbalanced

Signed-off-by: Josh Soref <[email protected]>

* chore: use example.com

* chore: fix reference for sidebar.registration

---------

Signed-off-by: Josh Soref <[email protected]>
Co-authored-by: Harttle <[email protected]>
2024-06-17 17:19:46 +08:00

3.8 KiB

title
title
Parse Parameters

Access Raw Parameters

As covered in Register Filters/Tags, tag parameters is available on tagToken.args as a raw string. For example:

// Usage: {% random foo bar coo %}
// Output: "foo", "bar" or "coo"
engine.registerTag('random', {
  parse(tagToken) {
    // tagToken.args === "foo bar coo"
    this.items = tagToken.args.split(' ')
  },
  render(context, emitter) {
    // get a random index
    const index = Math.floor(this.items.length * Math.random())
    // output that item
    emitter.write(this.items[index])
  }
})

Here's a JSFiddle version: https://jsfiddle.net/ctj364up/2/

Parse Parameters as Values

Sometimes we need more dynamic tags and want to pass values to the custom tag instead of static strings. Variables in LiquidJS can be literal (string, number, etc.) or a variable from current context scope.

The following modified template also contains 3 values to random from, but they're values instead of static strings. The first one is string literal, second one is an identifier, third one is a property access sequence containing two identifiers.

{% random "foo" bar obj.coo %}

It can be tricky to parse all these cases manually, but there's a Tokenizer class in LiquidJS you can make use of.

const { Liquid, Tokenizer, evalToken } = require('liquidjs')
engine.registerTag('random', {
  parse(tagToken) {
    const tokenizer = new Tokenizer(tagToken.args)
    this.items = []
    while (!tokenizer.end()) {
      // here readValue() returns a LiteralToken or PropertyAccessToken
      this.items.push(tokenizer.readValue())
    }
  },
  * render(context, emitter) {
    const index = Math.floor(this.items.length * Math.random())
    const token = this.items[index]
    // in LiquidJS, we use yield to wait for async call
    const value = yield evalToken(token, context)
    emitter.write(value)
  }
})

Calling this tag in scope { bar: "bar", obj: { coo: "coo" } } yields exactly the same result as the first example. See this JSFiddle: https://jsfiddle.net/ctj364up/3/

{% note info Async and Promises %} Async calls in LiquidJS are implemented by generators directly, for we can call generators in synchronous manner so this tag implementation is also valid for renderSync(), parseAndRenderSync(), renderFileSync(). If you need to await a promise in tag implementation, simply replace await somePromise with yield somePromise and keep * render() instead of async render() will do the trick. See Sync and Async for more details. {% endnote %}

Parse Key-Value Pairs as Named Parameters

Named parameters become very handy when there're optional parameters or lots of parameters, in which case the order of parameters is not important. This is exactly what Hash class is invented for.

{% random from:2, to:max %}

In the above example, we're trying to generate a random number in the range [2, max]. We'll use Hash to parse from and to parameters.

const { Liquid, Hash } = require('liquidjs')

engine.registerTag('random', {
  parse(tagToken) {
    // parse the parameters structure into `this.args`
    this.args = new Hash(tagToken.args)
  },
  * render(context, emitter) {
    // evaluate the parameters in `context`
    const {from, to} = yield this.args.render(context)
    const length = to - from + 1
    const value = from + Math.floor(length * Math.random())
    emitter.write(value)
  }
})

Rendering {% random from:2, to:max %} in scope { max: 10 } will generate a random number in the range [2, 10]. See this JSFiddle: https://jsfiddle.net/ctj364up/4/