Skip to content
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

Template parser issue when using curly braces for inline js or css #808

Open
stefanr opened this issue Jun 29, 2023 · 7 comments
Open

Template parser issue when using curly braces for inline js or css #808

stefanr opened this issue Jun 29, 2023 · 7 comments

Comments

@stefanr
Copy link

stefanr commented Jun 29, 2023

Sometimes when using curly braces for inline javascript or css styles inside a fluid template the parser breaks and does not further resolve variables from this point up until some other view helper is used via xml syntax or the scope (section, partial, ...) is closed.

I didn't look into the implementation in detail so it currently seems a little "random" at which point the parser stops working.

Example:

<f:variable name="test" value="foo" />
<div
  x-data="{
  test: null,
  init() {
    test = 'foo';
  }
  }"
>
  {test}
</div>

This correctly (or let's say as expected), gives: foo

This on the other hand (focus on the indentation):

<f:variable name="test" value="foo" />
<div
    x-data="{
      test: null,
      init() {
        test = 'foo';
      }
    }"
>
  {test}
</div>

... renders as: {test}

Placing a view helper before the variable output seems to fix wrong parser state:

<f:variable name="test" value="foo" />
<div
    x-data="{
      test: null,
      init() {
        test = 'foo';
      }
    }"
>
  <f:variable name="void" value="" />
  {test}
</div>

... renders again: foo

Any ideas? This issue is kind of a problem as one might not expect to destroy the following template code by changing some attributes that also render completely fine in the frontend.

Wrapping the problematic blocks like so x-data="<f:format.raw>{ ... }</f:format.raw>" is the current work around to fix this issue.

@sbuerk
Copy link
Contributor

sbuerk commented Jun 29, 2023

@stefanr Thank you for the issue report. However, I would say, this is not a bug. It is how it is worked and documentented.

{} are fluid specific chars which marks the start end end of variables or inline code. So they have a special meaning.

You are trying to mix this some how. There are multiple ways to mitigate this,
which are already documentend and explained, at least for the TYPO3 world here:

https://docs.typo3.org/m/typo3/guide-extbasefluid/main/en-us/Fluid/ThingsToKnow/JsAndInline.html

Granted, the context describes it for inline javascript, but this also counts for "json" or "JavaScript object like" markup creation.

It's a casual issue if you deal with kind of a parsed language, that special meaning chars needs to be escaped in the one or other way.

Not tested, but I guess following "should" work.

<f:variable name="test" value="foo" />
<f:format.cdata>
<div
  x-data="{
    test: null,
    init() {
      test = 'foo';
    }
  }"
>
</f:format.cdata>
  {test}
</div>

You could also wrapp the { and } of your "markup" code which should not be parsed into the format.raw viewhelper (also described in the link documentation page above).

Another solution is to create a custom viewhelper which creates the "data attribute" content and the structure instead of dealing wiht the definition in the markup if possible. Otherwise, I guess the cdata approav is the "best" way to do it as it avoids a lot of char based wrappings/escapings.

@radmiraal
Copy link

@sbuerk while agreeing on the {} special meaning I still think there's something going on. It seems like there's a randomness factor in this issue. I have a template with 1 x-data attribute, an x-bind:class attribute and those 2 attributes:

x-on:keyup.tab="<f:format.raw>Alpine.$data($el).__open()</f:format.raw>"
x-on:mouseup="<f:format.raw>Alpine.$data($el).__open()</f:format.raw>"

The following happens:

None of the attribute values wrapped: Simple inline var {foo} is not replace and rendered as {foo}

Only x-data wrapped, or x-data and the x-on:keyup.tab wrap: Same result

x-data and both of the attributes above wrapped: All works fine!

x-data wrapped and both attributes fully removed: Broken again

x-data wrapped and the x-class:bind wrapped, the attributes without wrapping: Also works fine

So although the issue does not occur when all json is wrapped it still feels like the bug appears quite randomly depending on the structure / formatting of the template... also seen it in other templates where just changing indent prevented the issue from occur...
So maybe this actually deserves some love...

@terminal8-af
Copy link

Another issue I've noticed is when adding a comment right after the opening brackets of a function such as here:

{f:security.nonce()}
<script>
	let map;
	function initMap() {
		// Map
		map = new Map(document.getElementById("map"), {
			zoom: 14,
		});
	}
	initMap();
</script>

This causes {f:security.nonce()} not to be parsed. However, upon removing the //Map comment the viewhelper is correctly parsed.

@s2b
Copy link
Contributor

s2b commented Mar 27, 2024

@AlexanderT8 In this case, you can probably wrap your inline script in a CDATA section.

I would also say that you should extract longer scripts to a separate file and create some kind of API to provide data from the DOM (like JSON in a data attribute).

@radmiraal
Copy link

@s2b I feel like there's loads of arguments against facing this is an actual bug... Of course this can be done in an API and longer scripts can be separated, but the parsing of Fluid simply breaks... Just focus on that fact...

I myself worked around the issue with workarounds like you suggest. But that doesn't mean the parsing ain't broken... I always loved Fluid and have an actual background in contribution but I decided to drop it because it simply doesn't work in this usecase at all. Unfortunately there're better alternatives that fit the usecase with for example alpinejs better. Which probably ain't a bad thing as we've to pick the right tool for the job of course. But still I would've loved to stick to Fluid...

@s2b
Copy link
Contributor

s2b commented Mar 27, 2024

@radmiraal Don't get me wrong, I acknowledge that this is a problem. I also know about the alternatives to Fluid and how they handle this. I just wanted to show the workarounds once again to "solve" the problem for the example given.

Currently, curly braces are an integral part of the Fluid syntax, and I fear that it won't be easy to modify/extend this without it being a breaking change. Currently, we're working on improving the ViewHelpers and improving the test coverage to be able to make bigger changes in the future. I hope that this issue will be such a change.

@simonschaufi
Copy link
Contributor

simonschaufi commented Oct 29, 2024

Actually this is also currently in the TYPO3 Core with the SystemEmail and inline CSS. I just wasted a lot of time simply because of this bug and even the core does it wrong! 😡 See https://github.com/TYPO3/typo3/blob/f947cbc75fb899b6179ad89cc25044c0d4746ebe/typo3/sysext/core/Resources/Private/Layouts/SystemEmail.html#L16-L323
I added a custom variable and was wondering why it was NOT printed even though the backgroundColor from typo3.systemConfiguration.backend.loginHighlightColor was working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants