liquidjs icon indicating copy to clipboard operation
liquidjs copied to clipboard

Building a tag that does not render but needs to do something

Open wturnerharris opened this issue 2 years ago • 1 comments

Hey @harttle - I was working on a tag to support a custom tag, and I'm running into a ParseError.

Here's the very basic filter:

engine.registerTag('debug', {
  parse: function (tagToken, remainTokens) {
    this.key = this.tokenizer.readIdentifier().content
    this.templates = []

    this.tokenizer.skipBlank()
    this.tokenizer.advance()

    this.stream = engine.parser.parseStream(remainTokens)
    this.stream.on('template', tpl => this.templates.push(tpl)).start().stop()
  },
  render: function (context, hash) {
    let { scopes } = context
    let scope = scopes.shift()
    let REP_STR = "-".repeat(10)
    let content = `${REP_STR}${(new Date()).toString()}\n${scope[this.key]}\n`
    fs.appendFile('./debug.log', content, err => {
      if (err) {
        console.error(err);
      }
    });
    return null
  }
});

The liquid code is also simple, and works as expected with this filter:

{%- assign file = "this,is,a,test" | split: "," -%}
{%- debug file -%}

However when a condition wraps this "function" it doesn't work and breaks:

{%- assign file = "this,is,a,test" | split: "," -%}
{%- if file != blank -%} // removing works
{%- debug file -%}
{%- endif -%} // removing works

And the error looks like this:

tag "endif" not found, file:/Sites/debug.liquid, line:4, col:1
   2| {%- if file != blank -%}
   3| {%- debug file -%}
>> 4| {%- endif -%}
      ^
ParseError: tag "endif" not found, file:/Users/westurner/Sites/humanscale/scripts/erp/debug.liquid, line:4, col:1

Intent and Progress:

This debug function should be simple—take the variable in the tag and output it in console or a log file. That's working as expected. However, because there's no "end tag" it seems like context of the tag is getting confused. If I remove the if condition or put the condition somewhere else, the tag works perfectly. If I remove the stream from starting, then it also doesn't throw an error, but the render function never runs. Ultimately nothing needs to render with this function, but something needs to happen, and it needs to be inside of a condition.

I was reviewing the "assign" tag from source and really tried replicating a similar definition because there is no end tag as well. I keep running into this parse error where "endif" is not found, but it's clearly there. So my assumption is that the parser is getting confused and not closing out properly. My assumption was that if I .stop() the stream it would signal the tag is closed. Is there something else I need to call to close it out?

wturnerharris avatar Jun 28 '23 21:06 wturnerharris

I think you should remove the line with “ this.stream.on”, it’s used to parse children templates and the debug tag has no children.

harttle avatar Jun 29 '23 02:06 harttle