-
Notifications
You must be signed in to change notification settings - Fork 71
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
Feature Request: Inline partials #63
Comments
The example I gave was not a use-case... more just to define a possible syntax (single asterisk for definition, double asterisk for usage). @devinrhode2 came up with the syntax in #59. Inline partials just make it easier to define reusable code snippets. Some partials do not need to be shared between templates, so there's no reason to go through all the work to define them in their own mustache template file. That's the use case this helps with. |
I'm curious where basic iterations would not take care of this. Can you think of a good scenario where inline partials are better than a basic iteration? |
The syntax for outputting a partial is already |
I think you're right about the syntax. We should continue to use One good scenario is where you iterate over something more than once, or iterate over two lists with similar items. In that case, you don't want to just copy/paste. You need a partial that you can reuse. Here's a snippet: {{>>person}}
<a href='/user/{{username}}'>{{name}}</a>
{{/person}}
<h1>Democrats</h1>
<ul>
{{#democrats}}
<li>{{>person}}</li>
{{/democrats}}
</ul>
<h1>Republicans</h1>
<ul>
{{#republicans}}
<li>{{>person}}</li>
{{/republicans}}
</ul> |
Solid use case, thanks |
Hi all. I think the use case still lacks proper definition. If the motivation is to avoid partials and to be DRY, then Mustache already provides a solution called lambdas:
If you have another motivation, @spudly, please refine it. |
I reuse my mustache files with two different implementations (PHP and JavaScript). For this reason, I don't like using lambdas and have to stick strictly to the spec. Also, using lambdas for something like this would mean that I would have to write the code in one language and then port it to the other. Then if I ever discover a bug in one I have to be sure to fix both, not just one. No thanks. Also, I precompile my templates using Hogan.js, which means I can't pass the contents of a lambda block to the lambda function (see twitter/hogan.js#75). |
Thanks @spudly for providing context. If I understand your points, I regret your "No thanks". Such a simple lambda would not be difficult to maintain in two languages. Seriously. It is not. Mustache suffers from the start from a lack of cross-language fostering. I, however, see cross-language concepts and APIs the key to help Mustache become a strong template engine that does not collapse as soon as the application leaves the trivial zone. Without an attempt at fostering solid and versatile APIs, Mustache will never go anywhere, and this repo will get more and more filled with issues that, seen from the outside, are all tiny additions that, if ever applied (and implemented by implementors), would turn Mustache into an ugly feature-bloated "tool" unable of having serious job done. I consider this as a sad waste. Not that I think that "inline partials" are an ugly feature per se. What I say is that quick "No thanks" dismissals do not go in the right direction. |
Please forgive my rudeness. I simply meant to say that I'd rather not maintain multiple copies of the same code. I do see the usefulness of lambdas; I just don't see them as a good solution to this particular problem. You're right that creating a link is easy to implement and maintain using lambdas, however that was just a simplified example. I expect many inline partials would be muich more complex. Drawing a table row for example would be a pain to write in a typical programming language, but simple enough using a partial. In that situation I would probably have to write a lambda that then processes another template to create the row html and then returns the html... but then you've just reinvented partials. Also, I believe there are scoping problems. Lambdas operate on a single parameter, that being the text within the lambda block. So |
I think you are not lucky and that you use sub-par libraries that prevent you to do your job. I don't care if they are the most-used/forked/watched JS or PHP libs. I care that they don't help you. I care that in order to have your job done, you would need to tweak them so much they would collapse, wasted under your iron will. And thus you give up, and complain about Mustache in this very repo. What you describe are plain and simple bugs in the implementations. Not in Mustache. One needs to be able to write a lambda that processes another template, and not to be feared by that. The API should make this simple, not scary, and linked to partials instead of opposed to them. One needs to write lambdas that inherit the current variable scope. If your Mustache implementation does not provide it, it's a toy, not a production tool. |
BTW, back to your topic. A user of GRMustache stores his templates in a custom home-made format, so that he can split them into named partials. He built is own inline-partial feature. Because he needed it. See for example https://github.com/tomaz/appledoc/blob/master/Templates/html/document-template.html |
It's not the libraries themselves. I don't expect the libraries to implement anything that is not in the spec. I want the feature added to the spec, so that both will implement it. That way I don't have to write two different template files to account for differences in the implementations. That's the whole point of having a spec, right?
Not trying to complain. Sorry if it came out that way. I'm simply requesting a feature be added to the spec and explaining why I think it would help.
A lack of a feature is not a bug. I did describe one bug that gives me grief with lambdas in Hogan.js, but that's the only one and I don't think it's even relevant to this issue.
I'm not scared to do it. I just don't see the point because I could just use a partial in the first place. Using lambdas to process another template seems like reinventing the wheel to me.
If I'm correct, the spec doesn't say that lambdas inherit the variable scope. Since I need this to work on multiple implementations, I only want to use features that are in the spec. This is why I put the feature request on the Mustache spec and not just on an implementation's repo. Lambdas as designed in the spec do not and can not solve my problem. Sure, there may be implementations that can do so, but that's not in the spec so anyone who reuses templates across different implementations can't use them. That's the reason why I use mustache and not handlebars or any other mustache extension. Here is an idea for a feature that could solve a problem. It's DRY and logic-free. Many other template libraries have it. I think it would be a good idea to add this to the spec. If whoever approves/writes the changes to the mustache spec doesn't agree, that's fine. |
That's precisely the kind of reasoning that happens because the implementations you are using are weak and force you into an uninspiring mental landscape. In these implementations, the versatility you are looking for is only accessible through partials. So you want more partials. And since those libraries provide inconvenient APIs for defining partials, you ask the language itself for more convenience - inline partials. Sorry if I sound like I wildly try to double guess you. But the fact that you "don't see" something does not mean there is nothing - just that you don't see it. So do, arguably, the implementations you're fighting with in your quest for doing the real job. The problem is the APIs, not the language syntax. For example, when you say "Using lambdas to process another template seems like reinventing the wheel to me", I see the opportunity to encapsulate code chunks in clear and focused units. I see Mustache that sneaks in the territory of Liquid templates. I see Mustache able to render All that is actually implemented in GRMustache, which is a Mustache library that allows you to write spec-compliant templates, but has been designed to help its users. Anyway. Now that you can't use lambdas because they are unusable in the libraries you are using, and because inline templates are for sure easier to implement, and thus may qualify as a reasonable goal, how could they look like? What about the
In order to help the implementors, we could say that inline templates have to be defined before their usage, in order to prevent a forced double parsing phase. In case of multiple definitions, the last definition before usage wins:
Question: should an inline definition be superseded by a partial that is programmatically defined? Or the opposite? In order to support Mustache implementations that can load templates and partials from a hierarchy of files and directories, allowing to define Some filesystem-based Mustache implementations also define absolute paths to partials ( Do you see any more rules that should be written? |
Have to agree with @groue on this one, definitely something that could/should be handled with a lambda. Or, in the case of Tache, you can simply return a compiled (or uncompiled) template object from your view method for rendering. I think this would be a more worthy addition to the spec as it has far more applications than just inline partials, something like:
|
Nice. Excellent convergence with GRMustache here :-) id data = @{
@"democrats": ...,
@"republicans": ...,
@"link": [GRMustacheTemplate templateFromString:@"<a href=\"/user/{{username}}\">{{name}}</a>" error:NULL],
};
NSString *rendering = [GRMustacheTemplate renderObject:data
fromResource:@"Document"
bundle:nil
error:NULL]; |
Dynamic partials discussed in #49 can be achieved with exactly the same logic, actually. I guess it's the same in Tache: id data = @{
@"democrats": ...,
@"republicans": ...,
@"link": [GRMustacheTemplate templateFromResource:@"Link" bundle:nil error:NULL],
};
NSString *rendering = [GRMustacheTemplate renderObject:data
fromResource:@"Document"
bundle:nil
error:NULL]; |
Maybe I'm wrong (because I am not familiar enough with objective-c) but what you're doing in that code looks like what I'm already doing with partials... I have separate template files that I compile and pass to a render function. These are then rendered wherever I reference them in the main template and they inherit the variable scope when they do so. What I want to do is to define the partials in the main template file so I don't have to define them in a separate file and pass them in. |
@spudly I see your problem. I was going to suggest creating a generic This touches on the larger subject of helpers which Mustache is currently lacking. I'm talking about helpers in the Handlebars sense, for example you could handle your problem with a 'capture' helper in Handlebars: {{! The following would capture the content into a 'captured' hash for later. }}
{{#capture "my_partial_name"}}
Some stuff I want to repeat
{{/capture}}
<h1>{{captured.my_partial_name}}</h1>
<footer>
<p>{{captured.my_partial_name}}</p>
</footer> I think something needs to be agreed upon when it comes to helper support in Mustache. The more I play with Handlebars, the more my helper envy grows. What are your thoughts @groue? |
@thelucid : this would require helpers/filters AND literal parsing. |
@groue Good point, although literals in Handlebars are only in the case of helpers, not a global change. They just get sent as arguments to the helper functions. I'm starting to think that this could address many of the questions that crop up in this repo. |
I suggest you quit this childish tone immediately. https://github.com/mustache/spec/blob/master/specs/%7Elambdas.yml#L96 shows that Mustache 1.1.2 lambdas inherit the current context when rendering: lambdas are the answer of Mustache 1.1.2 to your problem. Since the Mustache implementations you are using prevent you from using them, go and open issues in their repositories. @thelucid
Could they? I suggest you gather link to all issues that are related to literals in a global "literal" issue. Maybe the case for them will be so strong we'll just jump on the wagon right away. Or maybe not :-) |
(I really should improve my English and stop "suggesting" like a machine gun :-) |
@groue I didn't sense a childish tone from @spudly in the slightest, he simply wants to solve a problem in his Mustache workflow which is fair enough. I'm not suggesting that literals would solve many issues, I am suggesting that Handlebars style helpers (with basic literal support) would. You seem very quick to dismiss ideas unless they are your own. |
@groue I hardly think I'm being childish. If anything you have a hostile Thanks for pointing out that lambdas inherit variable scope. I was not Even so, I don't see how lambdas are a solution to my problem. The solution
|
@spudly Do you see how Handlebars style helpers would allow you to achieve this? |
@jamie, yes I do see how helpers could solve this problem pretty easily,
|
@spudly My experience with this spec repo has been that generally new language additions aren't accepted straight off. Instead, the maintainers look for more generic ways of solving the same issues that keep the core of Mustache as lean as possible (a good example of this is my ticket on dynamic partials and partial collections. Whilst this can be frustrating, it does sometimes result in a more generic solution that benefits the whole of Mustache, not just the initial problem. There are many issues that could benefit from a generic helper solution including your inline partial need, hence my suggestion. Given my experience on other tickets, I wouldn't hold out too much hope for getting inline partials added specifically, however if there is a more generic solution, this is more likely to be accepted (I feel your pain). |
@thelucid got the context right. Adding a feature each time somebody uses italics on want won't happen any time soon. Many ideas have been proposed here. None has been explored thoroughly enough. @spudly has been stuck on his inline partials, never telling how, for example, should their conflict with external partials be resolved (see above for the first unfinished exploration of his idea). @thelucid had a few difficulties with a "recorder" helper, and started gazing at Handlebars. I think invoking Handlebars is far too early. Handlebars is not the magic wand that solves all problems. Instead, you could focus first on a pair of lambdas, one that "records" its section, another that "replays" it. Is it possible? What is required to avoid recompilation? Any nasty corner cases? For the record, at the end of this comment is some GRMustache code that implements this record/replay pair without recompilation. Yes, a Mustache engine can do it. One argument for record/replay pairs is that they do not conflict with external partials. Maybe this conflict is a false problem. I wish we knew better. This requires in-depth inline partials analysis. If the idea of record/replay pairs remains solid after investigation, then we can explore the literals. I agree with @thelucid that it looks like literals look quite useful in conjunction with filters/helpers (see for instance groue/GRMustache#37, and another idea by @spudly: "variable defaults" #64, which used literals). Still I wish we had a better landscape of use cases that involve literals. The record/replay pair with GRMustache:
Rendering code: __block GRMustacheTag *recordedTag = nil;
id data = @{
@"democrats": ...
@"republicans": ...
@"record": [GRMustache renderingObjectWithBlock:^NSString *(GRMustacheTag *tag, GRMustacheContext *context, BOOL *HTMLSafe, NSError **error) {
// Record: save tag for later, and don't render anything.
recordedTag = tag;
return @"";
}],
@"replay": [GRMustache renderingObjectWithBlock:^NSString *(GRMustacheTag *tag, GRMustacheContext *context, BOOL *HTMLSafe, NSError **error) {
// Replay: render recorded tag.
return [recordedTag renderContentWithContext:context HTMLSafe:HTMLSafe error:error];
}],
};
NSString *rendering = [tempalte renderObject:data error:NULL]; |
Given my own experience, the spec maintainers @pvande, @defunkt and @janl won't show their nose and won't update the spec. Our only solution is to find a reasonably good solution for use cases, and implement them right away without spec support, hoping other implementors will follow. This is the really sad reality. A spec with maintainers who moved on. |
@groue I would say that nested helpers are a bad idea in a template anyway as things could get messy pretty fast. |
@groue If you needed nested helpers, you could accomplish with block helpers i.e. |
OK, that's better than nothing :-) That's still one extra compilation phase, since the record section has already been compiled when the record lambda is invoked.
For you it's expected that
Come on, are you like that? You a duck-typing guy? Again: GRMustache users do not open tickets saying "please allow me to compose helpers", or "please remove extra brackets and commas". Even less "please clean up the mess I've been messing up with using your messy library". |
Sure. Or use a syntax that does not suck. |
The lambda could receive the compiled tokens but the spec says that it should only receive text.
Yes, why would it? You are replaying one thing, capturing a new thing, then replaying that.
I'm not, but the thing I like about Mustache as it generally doesn't allow template authors to get in a mess. I can happily teach a designer the basics of Mustache, supply a JSON structure and he's unlikely to hang himself. With nested helpers, brackets etc. I see him trying all kinds of whacky stuff.
I don't see why you think |
@janl How do you feel about:
These three rules solve Dynamic Partials (#49 and #54), Partial Collections (#54) and no doubt, many other situations. All three rules have been tried and tested in Tache and GRMustache. Edit: Probably should go in another ticket but as we're discussing what should enter the spec here, felt like a good place to ask. I am happy to write the specs and submit a pull request. |
@thelucid Pretty limiting, hu? What about taking another point of view, and saying "my lib must allow people to render spec-compliant templates", instead of "my lib must behave exactly, no more, no less, as described by the spec"?
I'm talking about two distinct renderings of the same entire template, provided with the same input data.
OK. Let's build a toy, then. Thanks for the link. Let's look in details:
Oh. Handlebars is difficult to test. I feel sorry for them.
Oh. Handlebars is not mature enough. I feel sorry for them as well. GRMustache system is very simple, and thus extremely well tested, and extremely solid. Tags contain expressions. |
I'm running automated tests against the spec so if I want it to pass, it's the only option. Either that, or get the spec updated to allow tokens (or a template instance) to be passed to the lambda.
Oh, I see. I guess you'd just define a
Or you could make it more concise for simple cases and only require parentheses for nested calls like Ruby i.e.
|
Well, you have to pass the spec's tests. And your own for each of your additions. How do you think other implementors do, when they extend the language?
Yes, I have exactly the same problem. This is an encapsulation issue we need to address. If we do not, the user will have to document his code with sentences like "Remember to call reset! before using the template". This would be a real mess, this time.
You're border-line dishonest this time :-) I'm sure one reason for which you don't like much the Let's have a look at your actual Ruby code in Tache... Yeah, you're like me. You always use parenthesis when methods have arguments, and never use them when methods have no argument. You don't like ambiguity. Neither do I:
This is already implemented in GRMustache, and I don't want to switch to a poorer solution. I haven't yet needed named arguments in my own templates, as Handlebars do - I'd take inspiration from Ruby on that topic, I guess. |
Adding an additional argument would break the test I believe. Switching from text to tokens would definitely break the spec.
I think that if the user is going to litter their views with instance variable, it should be up to them to clear them. We could always provide some kind of
You are very quick with your accusations ;-) I hadn't even given the complexity of parsing a thought, just prefer the Handlebars syntax for the majority of cases.
You've not seen my ERB templates, that is when I do leave off parentheses as it makes for much more readable templates e.g. Named args could be handled the Ruby way too e.g. |
For what it's worth, I like the following syntax for defining an inline partial most, which I copied nearly verbatim from @groue in #63 (comment): {{=person}}
<a href=...
{{/person}}
{{#democrats}}
{{>person}}
{{/democrats}} The only change I made is that I repeated the I also like @groue's argument for using the Some considerations:
|
Following up on my previous comment: I just realized that the {{:person}}
<a href=...
{{/person}}
{{#democrats}}
{{>person}}
{{/democrats}} |
Any updates? I need this feature for my project. Here is the use case: |
I agree, I see exactly the same use-cases with inheritance partials / parent tag.
@jgonggrijp There is a small contradiction between your two proposals here, you want to avoid definition-precedence rules for inline partials, but still define precedence rules between inline partials and external partials. I think that your internal-vs-external conforms to the general intuition of "the nearest definition wins" (as in, say, the CSS cascade model): internal definitions are closer to the use-case so they take precedence. It should be possible to have a similar notion of lexical scope for internal definitions, and that would tell us what is the right behavior in presence of multiple declarations. To reformulate: what is the "visibility" of a partial/parent definition?
This is a simplification, but it's also a bit frustrating because it is nice/appealing/convenient to be allowed to define inline partials close to their use-sites, which may be at the end of a long section for example.
On the other hand, there is something we must be careful about: because the syntax for parent tag does not explicitly list its paremeters (unlike, say, a lambda-function syntax in most programming languages), there is a risk of ambiguity if we define an inline parent within an inline parent:
in this example, is I think the best solution in this case is to say that
Note: in this example I had to explicitly mark which inline definitions correspond to closed partials and which correspond to parent tags, because otherwise it would quickly get fairly confusing:
The fact that parent-inside-parent is a bit delicate while closed-inside-parent is not suggests that it's good to force people to be explicit about whether they are defining an inline parent or an inline closed partial. |
@lijiaqigreat
This project, and the present discussion, is about writing a specification for the template language feature; it is not about implementing the feature. If this feature becomes part of the specification, that will not immediately help you, because you need an actual implementation.
It appears you are already using a Mustache implementation. I see some non-standard syntax, so maybe it already implements inline partials? Otherwise, you can use "regular" external partials; they provide all the same features, except that you have to define the partial in a separate template file instead of in the main template. |
Yes, I would prefer the latter. According to the current spec, parents are exactly like partials, except that you can pass argument blocks (which necessitates the block end tag). External templates that are used as "plain" partials can still contain blocks, and external templates that don't contain any blocks can still be used as parents. It would not only be the simplest, but also the most consistent, to apply the same rule to inline partials/parents. In fact, it is probably a bit of misnomer to call them inline "partials" or "parents"; we should call them inline templates instead (or maybe "inline subtemplates", or "nested templates", to emphasize the nesting relationship). Whether another template is interpolated as a partial or a parent is decided at the site of interpolation, not at the site of definition.
I meant something else: I do not want to specify what should happen when multiple inline tempate definitions have the same name, because doing that just is not clean, can easily be avoided and should not be encouraged. I think that inline templates ideally also should not have the same name as pre-existing external templates, but since that is harder to avoid, specifying the precedence still seemed necessary. Note that the spec does not specifiy what to do when multiple external templates have the same name, either. I agree that "innermost wins" is a good rule in general. However, I believe there is no added value in allowing inline templates to "shadow" other inline templates. The template author is in full control of the template file, so if she wants to alternate between different versions of an inline template, she can just use different names. I should add that I am trying to keep my implementation as small as possible, and inline template names being tied to particular scopes (or being redefined at text order like Change Delimiter) is not going to help with that mission.
I would prefer the first option. Having to enforce that the inline template is invisible before the point of definition would significantly complicate my implementation. Some users will prefer to put all their inline templates at the top (bottom-up programmers), while others might want to put all of them at the bottom (top-down programmers). I don't think either order is inherently better than the other. On the other hand, the bottom-up order (definition before use) is probably a bit more consistent with Change Delimiter. We could also specifiy that the template must be visible after the definition, but leave it to the implementation to decide whether it is also visible before the definition. On the other other hand, external templates are unordered, so there is something to say for inline templates to be unordered as well. That would again speak in favor of them being visible throughout the containing template file.
Again, I would prefer not to tie the inline template to a particular scope, in order to keep the implementation compact.
External templates can be recursive, so I think it would be most consistent if inline templates can be, too. It also seems easiest to implement, since inline templates can be made of exactly the same "stuff" as external templates in that case.
Granted. I am not necessarily opposed to allowing the definition to appear within a nested scope, but in that case I would still want to "hoist" the inline template to the top scope, for the reasons I already discussed above.
I think this is a non-issue. Reading the spec closely (and figuring out how to pass it 100%), I found that any argument blocks provided to a template from the outside must be passed implicitly to any nested parents: Lines 182 to 209 in b2aeb3c
The outer template can also explicitly pass the block to the inner template, in which case the point becomes moot entirely:
Why on earth should inline subtemplates have their own inline sub-subtemplates in the first place, though? That, again, seems needlessly complicated to me. This could be another reason to allow them only at top scope, as I suggested before, or alternatively, just to disallow nesting them. I will demonstrate below why nesting inline templates adds no value.
I agree to this purely because of consistency.
I don't think that workaround should be necessary. The spec for inheritance in external templates allows multiple templates to have block parameters with the same name, so the same should be allowed for inline templates, as far as I'm concerned.
The above template will have exactly the same semantics if we deforest it:
Honestly, despite the fact that the workaround you're describing is convoluted and unnecessary, I do not even find it that confusing. As I wrote before, I believe that the distinction between partials and parents is purely at the site of interpolation ("in the eyes of the beholder", so to speak), not at the site of definition. Just |
(Hi folks. Would you please not quote my username @groue in your comments? I have long stopped working with Mustache, and I wish I would not be notified about threads started ~ 10 years ago. Thank you in advance!) |
Hi @groue. Please set the notification settings for this repository to "ignore". In that way, you will never be notified, not even if we mention you. Then you do not need to rely on the cooperation from us and future people who will not have seen your request, and we can continue mentioning you, which has a meaningful function for us because you were a major contributor in the past. |
Did that. Still, consider that notifying people 10 years after their last message in a thread is something that you should avoid, so that people do not have to make such a radical setup change. Consider that after I set to notification settings to "ignore", people who do intend to notify me through this repository won't be able to do so. Your actions have a negative effects on other people actions. I'm sure this was not your initial intention. Your cooperation, as well as cooperation from future people, is something we all rely on, regardless of all the features Github brings in order to cope with notification noise. Have a nice day! |
I'm aware. But I still would like to see this in the spec, so it's more likely than not to be in all implementations of mustache in the long run. |
@jgonggrijp your suggestions to have inline definitions scope over the whole file makes sense to me. (For me it makes even more sense to allow them inside sections, and then scope them only to this section.) But we still have to specify how they interact with partials: are they visible from within partials called in the file? Personally I would expect this to work:
but should that work in the case where |
Before I engage in the discussion again: please forgive my confrontational style. I read back my previous post and realized that it could come across as slightly polemic, but this is not what I'm after. I consider us to be on the same team: we try to arrive at a spec that works well enough for all implementers.
Glad to read that!
Honestly, I can see the sense in that as well. I imagine a use case like the following:
With
However, it is sensibility at a cost: the added complexity of implementation. Also, looking at the example, I wonder: do both inline templates really need to have the same name? Why not name them differently? I think that would even be less ambiguous and easier to understand.
Once we agree to name each inline template differently, we no longer need rules about how they might shadow each other. We can also leave the choice to users, whether they want to restrict themselves to using a particular inline template inside a particular scope or not. It becomes a matter of taste rather than a matter of necessity.
Ah, I realize you asked this before and I misunderstood the question. Sorry about that.
Agreed.
I think no: I would expect inline templates to be private to the file where they are defined. Otherwise, it becomes intractable where "external" partials/parents come from. In the following example, the author of
I would agree that there is a use case for "hackable" templates, but I think it should be opt-in, and blocks already address that need.
|
This discussion continues in #162. |
Partials are great, but it'd sure be nice to be able to define partials right inside the template that uses them. In most cases, the partials I create are only used by one parent template so it's a lot of extra work to create the partial the way it works right now. Also, a lot of my partials are one-liners. As a result, I often times end up just copy/pasting instead. It sure would be nice if we could define partials inline. See issue #59. This would allow us to write mini-templates that can be reused within the same template. Here's some possible syntax:
Definition:
Usage:
The text was updated successfully, but these errors were encountered: