-
Notifications
You must be signed in to change notification settings - Fork 225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added filter to apply dynamic filters #203
Conversation
I'll have to re-check the Stencil docs (on phone rn so not the best device to read them) but I thought Stencil already had a |
My bad, nvm, that tag indeed already exists but expects a filter name not a variable so isn't able to do dynamic filters. Forget I said anything |
@AliSoftware the implementation of filter node only converts the whole node to filter expression applied to the rendered content of the node, it does not resolve the name of the filter as variable. But that's something we can add too! Also I just find filter expression easier to use than filter node and better composable (chaining vs nesting) |
8e1e7b6
to
deba939
Compare
deba939
to
564ccb7
Compare
CHANGELOG.md
Outdated
@@ -12,6 +12,8 @@ | |||
[Ilya Puchka](https://github.com/yonaskolb) | |||
[#178](https://github.com/stencilproject/Stencil/pull/178) | |||
|
|||
- Added support for dynamic filter using `filter` filter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If (when?) #221 gets merged (merged), could you fix the format of this entry? Remove the newline above, add a .
and 2 spaces at the end, and credit yourself + link to this PR.
Sources/Parser.swift
Outdated
@@ -71,8 +71,24 @@ public class TokenParser { | |||
tokens.insert(token, at: 0) | |||
} | |||
|
|||
public func compileFilter(_ token: String) throws -> Resolvable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do these methods (compileFilter
, compileExpression
and compileResolvable
) have to be public?
Note: if they can be internal, don't forget to reset the Expression
protocol back to internal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So that they can be used by 3rd party extensions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ehm, do they need to be used by 3rd party extensions? Do you have a scenario where that'd be necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cant think of any now but if I needed it in filter
then it might be needed in something else complex too. Anyway, I don't see any harm in making these methods public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, a library should only expose the minimal surface necessary for a developer to use it. If at any point, something is missing, it can be added later on.
Maybe someone else has some thoughts on this point? @AliSoftware?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd normally agree with limiting the surface of the public API, but given all other stuff like parse(until:)
, nextToken()
and prependToken
are already public
too, I say it's fine by me.
TBH I haven't used Stencil as a library to be extended for a while now (only use case for us is StencilSwiftKit to extend Stencil), not sure there are many people using those features — main uses of this lib is probably just using it as-is to render templates, adding maybe some custom filters and that's all), that shouldn't really bother them.
BUT, if we're gonna have so much public API, then we should then definitely add doc-comments to them to explain to end users what they're supposed to be used for (especially to those not completely familiar with the concepts of a parser vs lexer etc, and proper definition of token etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea on the docs then. It took me quite a while to understand the codebase a bit, and the documentation in the code is quite sparse.
Except from the small changelog change, and some small access questions, this LGTM. |
Before I forget: This PR should document the changes in the |
bd1872a
to
2c411ca
Compare
@djbe comments addressed |
docs/builtins.rst
Outdated
``filter`` | ||
~~~~~~~~~ | ||
|
||
Applies filter by its name, provided as an argument. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applies the filter with the name (provided as argument) to the current expression.
docs/builtins.rst
Outdated
|
||
{{ string|filter:myfilter }} | ||
|
||
This expression will resolve `myfilter` variable and will apply filter with such name to `string` variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This expression will resolve the myfilter
variable, and it will apply the filter with that resolved name to the string
variable.
This will need a rebase, based on 0.12. Be careful when rebasing the changelog, as the entry will need to be moved to the right section (under |
# Conflicts: # CHANGELOG.md # Sources/ForTag.swift # Sources/IfTag.swift # Sources/Parser.swift # Sources/Variable.swift # Tests/StencilTests/ExpressionSpec.swift # Tests/StencilTests/FilterSpec.swift # Tests/StencilTests/ForNodeSpec.swift # Tests/StencilTests/VariableSpec.swift
@djbe I updated docs. We'll need this, in particular making |
Looks GTM. How come this branch is till out-of-date after that merge you did one hour ago? |
🤷♂️ |
filter:arg
will resolve its argument as filter expression which will allow to apply dynamic filters.The use case for that can be using Sourcery to generated code for Codable protocols and use different key coding strategies applied for different data models. It will allow to specify strategy as one of Stencil filters in a type annotation, i.e.
uppercaseFirstLetter
orcamelCaseToSnakeCase
, or even filter with arguments.Currently in template I have to check annotations against hardcoded set of filters to be able to apply them. With this change this template code
becomes this
and allows to use any registered filter without changing anything in template.