Shopify / liquid

Liquid markup language. Safe, customer facing template language for flexible web apps.

Home Page:https://shopify.github.io/liquid/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Access other tags of the same class from a custom liquid tag

asbjornu opened this issue · comments

I'm building a custom liquid tag which is used to build nodes in a tree. The tag takes a level argument, which affects its indentation in the tree. Pretty basic, but it works.

I would, however, like to make it a bit more complex by drawing lines between the nodes. To do this, I not only need to know the level of each node, but also whether it has children and/or siblings.

I could solve this by adding both has_siblings and has_children parameters to each node, but if the tree has many nodes, it quickly becomes unwieldy and hard to maintain. It would therefore be preferable to be able to programmatically find other, adjacent (formerly processed) liquid tags of the same class, and update their has_sibling and has_children fields as required. The question then becomes:

  1. How do I find adjacent nodes (custom Liquid tags) of the same class?
  2. Where do I store the required data for each node?

I've tried to poke at Liquid::ParseContext, but haven't found anything useful to do with it. I can see that the same ParseContext instance is shared between each tag instance, but ParseContext does not seem to expose a dictionary I can add items to.

I've thought that instead of using the ParseContext for state keeping, I can add a @@class_field to my custom tag class, but then I need to partition each instantiation of the tag by filename and vicinity somehow (I suppose Liquid::ParseContext#line_number can be used here). filename does not seem to be exposed by ParseContext.

I'm pretty sure I'm not going in the right direction here or missing something obvious, so some guidance would be highly appreciated! 😅 🙏🏼

I've found that the Liquid::Context passed to the render method contains the path I need to scope down the tags to the same file:

path = context.registers[:page]['path']

I've also found that Liquid::ParseContext contains the line_number so I can figure out the vicinity of adjacent tags:

line_number = parse_context.line_number

This would allow me to write a naïve tree-builder algorithm, had only Liquid::Context or something else containing the path been available on initialize and not just on render.