marksy icon indicating copy to clipboard operation
marksy copied to clipboard

Inconsistent rendering of children

Open mmmaaatttttt opened this issue 7 years ago • 6 comments

Hi there,

I've built a small component inside of which I want to render some text. The text, however, has curly braces inside of it, and this isn't playing nicely with the renderer. Here's a minimal working example:

import React, { createElement } from "react";
import marksy from "marksy/components";

const compile = marksy({
  createElement,
  components: {
    Test(props) {
      return (
        <div>
          This is a test.
          <p>{props.children}</p>
        </div>
      );
    }
  }
});

compile("<Test>hi</Test>") // tree is an array with 1 element
compile("<Test>{hi}</Test>") // tree is an empty array!

Right now this is failing silently: I traced the issue to this catch, which is a no-op:

https://github.com/cerebral/marksy/blob/86b9fd3e4f67f7d8037a6968d04b33b60a179d3b/src/components.js#L38

I tried console.logging the error, and discovered that the compiler is throwing a reference error for hi being undefined.

To try to work around this issue, I tried different ways of getting the curly braces to not be evaluated as though I'm in JSX. All of them have failed for different reasons:

compile("<Test>{`{hi}`}</Test>") 
// compiler treats `{hi}` as a code block

compile("<Test>{'{hi}'}</Test>")
// SyntaxError: unknown: Unexpected character '‘' (1:7)
// > 1 | <Test>{‘{hi}’}</Test>

compile("<Test>{\"{hi}\"}</Test>")
// SyntaxError: unknown: Unexpected character '“' (1:7)
// > 1 | <Test>{“{hi}”}</Test>

Interestingly, this is also an issue for some built-in elements, but not all:

compile("<p>{hi}</p>") // ReferenceError
compile("<h1>{hi}</h1>") // ReferenceError
compile("<div>{hi}</div>") // ReferenceError
compile("<a>{hi}</a>") // this works
compile("<span>{hi}</span>") // this works

I can get around this issue for now by passing my string as a prop to the component rather than trying to make it a child. But this behavior feels like a bug to me. Any idea what's happening?

Thanks!

mmmaaatttttt avatar Oct 14 '17 16:10 mmmaaatttttt

Here's another one!

compile("<Test>{\`{hi}\`}</Test>")
// SyntaxError: unknown: Unexpected token (1:8)
// > 1 | <Test>{{{0}}}</Test>

mmmaaatttttt avatar Oct 14 '17 16:10 mmmaaatttttt

Any updates on this?

Stanley-Jovel avatar Nov 02 '17 17:11 Stanley-Jovel

@mmmaaatttttt @Stanley-Jovel Hi there :) Sorry I am late on responses, but just got out of paternity leave and back to work.

compile("<Test>{\`{hi}\`}</Test>")

That does not really make any sense because hi is an undefined variable. Not sure what you expect the output should be? It would be like writing:

function Comp () {
  return <div>{hi}</div>
}

There is no reference to hi anywhere.... maybe you could explain a bit more what you are trying to achieve? Might be a different way :)

christianalfoni avatar Nov 06 '17 07:11 christianalfoni

Hey @christianalfoni,

Congratulations! I can't speak to @Stanley-Jovel, but I'm just trying to escape the curly braces so that the children just get evaluated as a string.

mmmaaatttttt avatar Nov 06 '17 17:11 mmmaaatttttt

@mmmaaatttttt Hi again and thanks :)

I would suggest this is what you want?

compile("<Test>{'hi'}</Test>")

It is like:

<Test>{"hi"}</Test>

While above example looks like this:

<Test>"{hi}"</Test>

That does not work :) Or you could do:

<Test>{"{hi}"}</Test>

If you want to include curlies in the string :)

Do I understand this correctly?

christianalfoni avatar Nov 06 '17 18:11 christianalfoni

Hey @christianalfoni !

Sorry for the extreme delay. I ended up using a workaround by passing down a prop rather than using the children, but I'm circling back to this issue now.

Unfortunately, I don't think the fix you suggested does the trick, because the behavior of the compiler is a little strange when curly braces are in the string.

The issue comes up even with a built-in p-tag. Check it out (this is the behavior I see using 6.0.3):

import marksy from "marksy/components";
import React, { createElement } from "react";

// make a minimal compiler
const compile = marksy({
  createElement
});

compile("<p>'hi'</p>"); // the tree is an array with one element, as expected
compile("<p>{'hi'}</p>"); // the tree is empty (?!)
compile("<p>'{hi}'</p>"); // the tree is empty again (?!?!)
compile("<p>'awelf{hi'</p>"); // the tree is empty again (?!?!?!)
compile("<p>'awelf}hi'</p>"); // the tree has one element

It seems like the presence of a single curly brace inside of a string inside of the p tag is enough to throw off the compilation. Also, this behavior doesn't exist for all elements; a tags, for example, behave as you'd expect.

mmmaaatttttt avatar Apr 07 '18 22:04 mmmaaatttttt