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

In-browser compilation with spaces after opening { bracket #2988

Open
mrmattson opened this issue Dec 6, 2023 · 3 comments
Open

In-browser compilation with spaces after opening { bracket #2988

mrmattson opened this issue Dec 6, 2023 · 3 comments

Comments

@mrmattson
Copy link

I found an issue during in-browser compilation where a space after the opening bracket of onclick={ breaks the compiler.

This doesn't compile:

<template id="my-tag-example">
  <my-tag-example>
    <p>{ state.message }</p>
    <button onclick={ helloAgain }>Click Me!</button>
    <script>
      export default {
        onMounted() {
          this.update({
            message: this.props.message
          })
        },
        helloAgain() {
          this.update({
            message: this.state.message + ' again'
          })
        }
      }
    </script>
  </my-tag-example>
</template>

In the browser console, if I do this:

const tagString = document.getElementById('my-tag-example').innerHTML
const {code} = riot.compileFromString(tagString)
code

code contains this:

export default {
  css: null,

  exports: {
    onMounted() {
      this.update({
        message: this.props.message
      })
    },

    helloAgain() {
      this.update({
        message: this.state.message + ' again'
      })
    }
  },

  template: (
    template,
    expressionTypes,
    bindingTypes,
    getComponent
  ) => template(
    '<p expr0="expr0"> </p><button onclick="{" helloagain }>Click Me!</button>',
    [
      {
        redundantAttribute: 'expr0',
        selector: '[expr0]',

        expressions: [
          {
            type: expressionTypes.TEXT,
            childNodeIndex: 0,
            evaluate: _scope => _scope.state.message
          }
        ]
      }
    ]
  ),

  name: 'my-tag-example'
};

This compiles:

<template id="my-tag-example">
  <my-tag-example>
    <p>{ state.message }</p>
    <button onclick={helloAgain}>Click Me!</button>
    <script>
      export default {
        onMounted() {
          this.update({
            message: this.props.message
          })
        },
        helloAgain() {
          this.update({
            message: this.state.message + ' again'
          })
        }
      }
    </script>
  </my-tag-example>
</template>

And this compiles:

<template id="my-tag-example">
  <my-tag-example>
    <p>{ state.message }</p>
    <button onclick="{ helloAgain }">Click Me!</button>
    <script>
      export default {
        onMounted() {
          this.update({
            message: this.props.message
          })
        },
        helloAgain() {
          this.update({
            message: this.state.message + ' again'
          })
        }
      }
    </script>
  </my-tag-example>
</template>
@GianlucaGuarini
Copy link
Member

The native browser template inner html is something we can't control with our compiler. However the Riot attribute expressions support also single and double quotes to circumvent this issue.
Other users experienced similar issues so it could be worth to mention it in our documentation. Would you mind opening a PR adding this information? Thanks

@exside
Copy link

exside commented Apr 18, 2024

To clarify what @GianlucaGuarini said above about innerHTML on template tag within a browser.

If you run document.querySelector('#my-tag-example').innerHTML on the page where you added your component for in-browser compilation, you'll get:

\n  <my-tag-example>\n    <p>{ state.message }</p>\n    <button onclick="{" helloagain="" }="">Click Me!</button>\n    \x3Cscript>\n      export default {\n        onMounted() {\n          this.update({\n            message: this.props.message\n          })\n        },\n        helloAgain() {\n          this.update({\n            message: this.state.message + ' again'\n          })\n        }\n      }\n    \x3C/script>\n  </my-tag-example>\n

you can easily see that the missing quotes around the onclick value mess up the dom parsing in the browser => <button onclick="{" helloagain="" }="">Click Me!</button> so it's not really an issue with a compiler, just write consistent HTMl and use quotes 😉

@kachurun
Copy link
Contributor

What about this text to the In-Browser Compilation section


Important Note: When writing expressions within attributes (like onclick={ expression }), ensure that there are no spaces between the { and the expression.

For example:
This will not compile correctly:

<button onclick={ helloAgain }>Click Me!</button>

Instead, use either of the following formats:

<button onclick={helloAgain}>Click Me!</button>
<button onclick="{ helloAgain }">Click Me!</button>

This is due to how the browser parses the innerHTML of the tag, which can affect the way Riot.js handles the compilation. Always ensure consistent HTML formatting to avoid these issues.

For more details, see the related GitHub issue #2988

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

No branches or pull requests

4 participants