Closed djbe closed 6 years ago
Note: the reason I went with the object.$property
syntax instead of something like object[property]
is that there's no cross-platform regex support (NSRegularExpression is macOS only).
I love the idea.
It's a shame that we can't use subscript for that though
1) FWIW I think you could be able to use .[prop]
instead of .$prop
even without using regex, eg:
if bit.hasPrefix("[") && bit.hasSuffix("]"),
let resolved = try? Variable(String(bit.dropFirst().dropLast())).resolve(context),
…
2) but even with such a solution that would still mean the syntax need to use the dot, and would look like object.[property]
where what we would ideally want would be object[property]
. So in that regard if the solution needs for technical reasons to use a dot then I prefer o.$p
to o.[p]
and if we want to support o[p]
we'd have to find a different solution for the implementation
3) Before validating that kind of syntax I'd suggest to look at the syntax Jinja uses for such feature (if it does support it, that is). We have to remember that Stencil is inspired by Jinja-like template engines and it's better for the end user of we can use the same or very similar syntax and tags whenever possible/relevant for similar features.
Jinja uses braces for lookup: https://stackoverflow.com/questions/27208891/jinja2-dictonary-lookup-using-a-variable-key#27208914
Damn so that would still be better to find a way to do that with braces without dot, both because it feels more natural and because it's similar to Jinja… but I guess you tried to find a solution for that already?
I'm honestly not sure how to tackle that without regular expressions, and without blowing this code up into some massive thing.
I didn't test this code, but this might work:
fileprivate func lookup() -> [String] {
return variable.split(separator: ".")
.flatMap({ $0.split(separator: "[", maxSplits: 1) })
.map({ String($0).trim(character: "]") })
}
This will though only work on single brackets, like foo[bar]
, but not foo[bar[abc]]
, which I'm not sure we should even support.
@AliSoftware good point about filter.
Simple alternative to all of that can be a filter like foo|attr:bar
(or with any other maningful name)
Can also try split(maxSplits: 2, whereSeparator isSeparator: { $0 == "[" || $0 == "]" })
variant where separator can be either [
or ]
so there will be no need for trim, I guess.
@ilyapuchka Mmmh interesting idea to use a filter to extract the property. But that would still mean we couldn't apply a filter on that filter 😅
it would enable us to do object|attr:property.name
to do the equivalent of Jinja's object[property.name]
but we still wouldn't be able to do the equivalent of Jinja's object[property.name|lowercase]
for example
I really think the right syntax is to use the same syntax as Jinja, the question is how to implement it in Stencil without breaking all the code…
@AliSoftware true. We can for that add support for brackets in filter expressions item|attr:(bar|attr:abc)
which might be also useful in general. I have added that for boolean expressions in #165
I'm working on a solution right now, might take a bit. I'm going to iterate over the characters (in the lookup
function), and keep track if I'm in a lookup (between [
and ]
). I'll even support multiple lookup levels 😄
Since the force push is hiding the commit comments:
Does that mean that
object[[[]]]...[]..[]
would be valid, as you filter out empty bits?
We should define the syntax a bit more. To make things a bit easer:
{{ [property] }}
be valid? (see first test, it should IMO){{ object[[[stuff]]] }}
is valid....
was already valid in Stencil.
This allows users to refer to variables (and properties) using indirection.
Let's say for example we have the following context:
A user can then write:
To produce: